mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
Input updates for 6.5 merge window:
- improvements to PS/2 handling for case when EC has already latched a scancode in the data register, but the kernel expects to receive an ACK to a command it sent to a device (such as keyboard LED toggle) - input drivers for devices connected over I2C bus have been switched back to using [new] .probe() - uinput allows userspace to inject timestamps for input events - support for capacitive keys in Atmel touch controller driver - assorted fixes to drv260x, pwm-vibra, ili210x, adxl34x, and other drivers. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCZJtgIgAKCRBAj56VGEWX nKjaAP9lj2QkBfMssBAXVM2RIpXpsBcx+Z2kxZ3sFIUD+Cah7gEAuypzoVHw+n6+ yLMiwEbHWt8514CK0wnsea1UVFW87AY= =lbD/ -----END PGP SIGNATURE----- Merge tag 'input-for-v6.5-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input Pull input updates from Dmitry Torokhov: - improvements to PS/2 handling for case when EC has already latched a scancode in the data register, but the kernel expects to receive an ACK to a command it sent to a device (such as keyboard LED toggle) - input drivers for devices connected over I2C bus have been switched back to using [new] .probe() - uinput allows userspace to inject timestamps for input events - support for capacitive keys in Atmel touch controller driver - assorted fixes to drv260x, pwm-vibra, ili210x, adxl34x, and other drivers * tag 'input-for-v6.5-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits) Input: pm8941-powerkey - fix debounce on gen2+ PMICs MAINTAINERS: Adjust Qualcomm driver globbing Input: gameport - provide default trigger() and read() Input: tps65219-pwrbutton - use regmap_set_bits() Input: tps65219-pwrbutton - convert to .remove_new() Input: tests - add test to cover all input_grab_device() function Input: gpio-keys - use input_report_key() Input: xpad - spelling fixes for "Xbox" Input: add HAS_IOPORT dependencies Input: libps2 - do not discard non-ack bytes when controlling LEDs Input: libps2 - introduce common interrupt handler Input: libps2 - fix aborting PS/2 commands Input: libps2 - fix NAK handling Input: libps2 - rework handling of command response Input: libps2 - remove special handling of ACK for command byte Input: libps2 - attach ps2dev instances as serio port's drvdata Input: Switch i2c drivers back to use .probe() dt-bindings: input: cypress,cyapa: convert to dtschema Input: adxl34x - do not hardcode interrupt trigger type Input: pwm-vibra - add support for enable GPIO ...
This commit is contained in:
commit
86e203edf2
@ -14,6 +14,9 @@ description: |
|
||||
Atmel maXTouch touchscreen or touchpads such as the mXT244
|
||||
and similar devices.
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: atmel,maxtouch
|
||||
@ -60,6 +63,10 @@ properties:
|
||||
or experiment to determine which bit corresponds to which input. Use
|
||||
KEY_RESERVED for unused padding values.
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
|
||||
atmel,wakeup-method:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
|
@ -1,42 +0,0 @@
|
||||
Cypress I2C Touchpad
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "cypress,cyapa".
|
||||
- reg: I2C address of the chip.
|
||||
- interrupts: interrupt to which the chip is connected (see interrupt
|
||||
binding[0]).
|
||||
|
||||
Optional properties:
|
||||
- wakeup-source: touchpad can be used as a wakeup source.
|
||||
- pinctrl-names: should be "default" (see pinctrl binding [1]).
|
||||
- pinctrl-0: a phandle pointing to the pin settings for the device (see
|
||||
pinctrl binding [1]).
|
||||
- vcc-supply: a phandle for the regulator supplying 3.3V power.
|
||||
|
||||
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
|
||||
|
||||
Example:
|
||||
&i2c0 {
|
||||
/* ... */
|
||||
|
||||
/* Cypress Gen3 touchpad */
|
||||
touchpad@67 {
|
||||
compatible = "cypress,cyapa";
|
||||
reg = <0x67>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
/* Cypress Gen5 and later touchpad */
|
||||
touchpad@24 {
|
||||
compatible = "cypress,cyapa";
|
||||
reg = <0x24>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
/* ... */
|
||||
};
|
49
Documentation/devicetree/bindings/input/cypress,cyapa.yaml
Normal file
49
Documentation/devicetree/bindings/input/cypress,cyapa.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/cypress,cyapa.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Cypress All Points Addressable (APA) I2C Touchpad / Trackpad
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: cypress,cyapa
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
vcc-supply:
|
||||
description: 3.3V power
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
trackpad@67 {
|
||||
reg = <0x67>;
|
||||
compatible = "cypress,cyapa";
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-parent = <&gpx1>;
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
@ -32,6 +32,8 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
enable-gpios: true
|
||||
|
||||
vcc-supply: true
|
||||
|
||||
direction-duty-cycle-ns:
|
||||
|
@ -40,6 +40,8 @@ properties:
|
||||
linux,keycodes:
|
||||
description: EV_ABS specific event code generated by the axis.
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
patternProperties:
|
||||
"^button@[0-9]+$":
|
||||
type: object
|
||||
|
@ -4,16 +4,16 @@ xpad - Linux USB driver for Xbox compatible controllers
|
||||
|
||||
This driver exposes all first-party and third-party Xbox compatible
|
||||
controllers. It has a long history and has enjoyed considerable usage
|
||||
as Window's xinput library caused most PC games to focus on Xbox
|
||||
as Windows' xinput library caused most PC games to focus on Xbox
|
||||
controller compatibility.
|
||||
|
||||
Due to backwards compatibility all buttons are reported as digital.
|
||||
This only effects Original Xbox controllers. All later controller models
|
||||
This only affects Original Xbox controllers. All later controller models
|
||||
have only digital face buttons.
|
||||
|
||||
Rumble is supported on some models of Xbox 360 controllers but not of
|
||||
Original Xbox controllers nor on Xbox One controllers. As of writing
|
||||
the Xbox One's rumble protocol has not been reverse engineered but in
|
||||
the Xbox One's rumble protocol has not been reverse-engineered but in
|
||||
the future could be supported.
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ I've tested this with Stepmania, and it works quite well.
|
||||
Unknown Controllers
|
||||
-------------------
|
||||
|
||||
If you have an unknown xbox controller, it should work just fine with
|
||||
If you have an unknown Xbox controller, it should work just fine with
|
||||
the default settings.
|
||||
|
||||
HOWEVER if you have an unknown dance pad not listed below, it will not
|
||||
@ -123,7 +123,7 @@ can be found on the net ([1]_, [2]_, [3]_).
|
||||
|
||||
Thanks to the trip splitter found on the cable you don't even need to cut the
|
||||
original one. You can buy an extension cable and cut that instead. That way,
|
||||
you can still use the controller with your X-Box, if you have one ;)
|
||||
you can still use the controller with your Xbox, if you have one ;)
|
||||
|
||||
|
||||
|
||||
|
@ -184,7 +184,7 @@ Gamepads report the following events:
|
||||
|
||||
Many pads also have a third button which is branded or has a special symbol
|
||||
and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo
|
||||
"HOME" button, the XBox "X"-button or Sony "PS" button.
|
||||
"HOME" button, the Xbox "X" button or the Sony PlayStation "PS" button.
|
||||
|
||||
- Rumble:
|
||||
|
||||
|
@ -2581,9 +2581,9 @@ F: arch/arm/boot/dts/qcom-*.dtsi
|
||||
F: arch/arm/configs/qcom_defconfig
|
||||
F: arch/arm/mach-qcom/
|
||||
F: arch/arm64/boot/dts/qcom/
|
||||
F: drivers/*/*/pm8???-*
|
||||
F: drivers/*/*/qcom*
|
||||
F: drivers/*/*/qcom/
|
||||
F: drivers/*/pm8???-*
|
||||
F: drivers/*/qcom*
|
||||
F: drivers/*/qcom/
|
||||
F: drivers/bluetooth/btqcomsmd.c
|
||||
|
@ -168,7 +168,7 @@ config INPUT_EVBUG
|
||||
|
||||
config INPUT_KUNIT_TEST
|
||||
tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS
|
||||
depends on INPUT && KUNIT=y
|
||||
depends on INPUT && KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Say Y here if you want to build the KUnit tests for the input
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gameport.h>
|
||||
@ -21,8 +22,6 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timekeeping.h>
|
||||
|
||||
/*#include <asm/io.h>*/
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Generic gameport layer");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -518,6 +517,16 @@ void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
|
||||
}
|
||||
EXPORT_SYMBOL(gameport_set_phys);
|
||||
|
||||
static void gameport_default_trigger(struct gameport *gameport)
|
||||
{
|
||||
outb(0xff, gameport->io);
|
||||
}
|
||||
|
||||
static unsigned char gameport_default_read(struct gameport *gameport)
|
||||
{
|
||||
return inb(gameport->io);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare gameport port for registration.
|
||||
*/
|
||||
@ -536,6 +545,11 @@ static void gameport_init_port(struct gameport *gameport)
|
||||
if (gameport->parent)
|
||||
gameport->dev.parent = &gameport->parent->dev;
|
||||
|
||||
if (!gameport->trigger)
|
||||
gameport->trigger = gameport_default_trigger;
|
||||
if (!gameport->read)
|
||||
gameport->read = gameport_default_read;
|
||||
|
||||
INIT_LIST_HEAD(&gameport->node);
|
||||
spin_lock_init(&gameport->timer_lock);
|
||||
timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0);
|
||||
|
@ -190,6 +190,7 @@ static int input_handle_abs_event(struct input_dev *dev,
|
||||
unsigned int code, int *pval)
|
||||
{
|
||||
struct input_mt *mt = dev->mt;
|
||||
bool is_new_slot = false;
|
||||
bool is_mt_event;
|
||||
int *pold;
|
||||
|
||||
@ -210,6 +211,7 @@ static int input_handle_abs_event(struct input_dev *dev,
|
||||
pold = &dev->absinfo[code].value;
|
||||
} else if (mt) {
|
||||
pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST];
|
||||
is_new_slot = mt->slot != dev->absinfo[ABS_MT_SLOT].value;
|
||||
} else {
|
||||
/*
|
||||
* Bypass filtering for multi-touch events when
|
||||
@ -228,8 +230,8 @@ static int input_handle_abs_event(struct input_dev *dev,
|
||||
}
|
||||
|
||||
/* Flush pending "slot" event */
|
||||
if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
|
||||
input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
|
||||
if (is_new_slot) {
|
||||
dev->absinfo[ABS_MT_SLOT].value = mt->slot;
|
||||
return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
|
||||
}
|
||||
|
||||
|
@ -292,33 +292,33 @@ config JOYSTICK_JOYDUMP
|
||||
module will be called joydump.
|
||||
|
||||
config JOYSTICK_XPAD
|
||||
tristate "X-Box gamepad support"
|
||||
tristate "Xbox gamepad support"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
select USB
|
||||
help
|
||||
Say Y here if you want to use the X-Box pad with your computer.
|
||||
Say Y here if you want to use Xbox pads with your computer.
|
||||
Make sure to say Y to "Joystick support" (CONFIG_INPUT_JOYDEV)
|
||||
and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well.
|
||||
|
||||
For information about how to connect the X-Box pad to USB, see
|
||||
For information about how to connect the Xbox pad to USB, see
|
||||
<file:Documentation/input/devices/xpad.rst>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called xpad.
|
||||
|
||||
config JOYSTICK_XPAD_FF
|
||||
bool "X-Box gamepad rumble support"
|
||||
bool "Xbox gamepad rumble support"
|
||||
depends on JOYSTICK_XPAD && INPUT
|
||||
select INPUT_FF_MEMLESS
|
||||
help
|
||||
Say Y here if you want to take advantage of xbox 360 rumble features.
|
||||
Say Y here if you want to take advantage of Xbox 360 rumble features.
|
||||
|
||||
config JOYSTICK_XPAD_LEDS
|
||||
bool "LED Support for Xbox360 controller 'BigX' LED"
|
||||
bool "LED Support for the Xbox 360 controller Guide button"
|
||||
depends on JOYSTICK_XPAD && (LEDS_CLASS=y || LEDS_CLASS=JOYSTICK_XPAD)
|
||||
help
|
||||
This option enables support for the LED which surrounds the Big X on
|
||||
XBox 360 controller.
|
||||
Xbox 360 controllers.
|
||||
|
||||
config JOYSTICK_WALKERA0701
|
||||
tristate "Walkera WK-0701 RC transmitter"
|
||||
|
@ -348,7 +348,7 @@ static struct i2c_driver as5011_driver = {
|
||||
.driver = {
|
||||
.name = "as5011",
|
||||
},
|
||||
.probe_new = as5011_probe,
|
||||
.probe = as5011_probe,
|
||||
.remove = as5011_remove,
|
||||
.id_table = as5011_id,
|
||||
};
|
||||
|
@ -137,7 +137,7 @@ static struct i2c_driver qwiic_driver = {
|
||||
.of_match_table = of_match_ptr(of_qwiic_match),
|
||||
},
|
||||
.id_table = qwiic_id_table,
|
||||
.probe_new = qwiic_probe,
|
||||
.probe = qwiic_probe,
|
||||
};
|
||||
module_i2c_driver(qwiic_driver);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* X-Box gamepad driver
|
||||
* Xbox gamepad driver
|
||||
*
|
||||
* Copyright (c) 2002 Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
* 2004 Oliver Schwartz <Oliver.Schwartz@gmx.de>,
|
||||
@ -23,8 +23,8 @@
|
||||
* - ITO Takayuki for providing essential xpad information on his website
|
||||
* - Vojtech Pavlik - iforce driver / input subsystem
|
||||
* - Greg Kroah-Hartman - usb-skeleton driver
|
||||
* - XBOX Linux project - extra USB id's
|
||||
* - Pekka Pöyry (quantus) - Xbox One controller reverse engineering
|
||||
* - Xbox Linux project - extra USB IDs
|
||||
* - Pekka Pöyry (quantus) - Xbox One controller reverse-engineering
|
||||
*
|
||||
* TODO:
|
||||
* - fine tune axes (especially trigger axes)
|
||||
@ -52,7 +52,7 @@
|
||||
* 2002-07-17 - 0.0.5 : simplified d-pad handling
|
||||
*
|
||||
* 2004-10-02 - 0.0.6 : DDR pad support
|
||||
* - borrowed from the XBOX linux kernel
|
||||
* - borrowed from the Xbox Linux kernel
|
||||
* - USB id's for commonly used dance pads are present
|
||||
* - dance pads will map D-PAD to buttons, not axes
|
||||
* - pass the module paramater 'dpad_to_buttons' to force
|
||||
@ -454,49 +454,49 @@ static const signed short xpad_btn_paddles[] = {
|
||||
{ XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) }
|
||||
|
||||
static const struct usb_device_id xpad_table[] = {
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
|
||||
XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */
|
||||
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */
|
||||
XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */
|
||||
XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */
|
||||
XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */
|
||||
XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */
|
||||
XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */
|
||||
XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */
|
||||
XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */
|
||||
XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */
|
||||
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz Xbox 360 controllers */
|
||||
{ USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
|
||||
XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */
|
||||
XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */
|
||||
XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */
|
||||
XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */
|
||||
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
|
||||
XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
|
||||
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */
|
||||
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane Xbox 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x146b), /* Bigben Interactive controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */
|
||||
XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */
|
||||
XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
|
||||
XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
|
||||
XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */
|
||||
XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */
|
||||
XPAD_XBOX360_VENDOR(0x24c6), /* PowerA controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */
|
||||
XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */
|
||||
XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */
|
||||
XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */
|
||||
XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */
|
||||
XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */
|
||||
XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */
|
||||
XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */
|
||||
XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke Xbox One pad */
|
||||
XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */
|
||||
XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */
|
||||
XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */
|
||||
{ }
|
||||
@ -724,7 +724,7 @@ static void xpad360w_poweroff_controller(struct usb_xpad *xpad);
|
||||
* Completes a request by converting the data into events for the
|
||||
* input subsystem.
|
||||
*
|
||||
* The used report descriptor was taken from ITO Takayukis website:
|
||||
* The used report descriptor was taken from ITO Takayuki's website:
|
||||
* http://euc.jp/periphs/xbox-controller.ja.html
|
||||
*/
|
||||
static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
|
||||
@ -1569,7 +1569,7 @@ struct xpad_led {
|
||||
};
|
||||
|
||||
/*
|
||||
* set the LEDs on Xbox360 / Wireless Controllers
|
||||
* set the LEDs on Xbox 360 / Wireless Controllers
|
||||
* @param command
|
||||
* 0: off
|
||||
* 1: all blink, then previous setting
|
||||
@ -2229,5 +2229,5 @@ static struct usb_driver xpad_driver = {
|
||||
module_usb_driver(xpad_driver);
|
||||
|
||||
MODULE_AUTHOR("Marko Friedemann <mfr@bmx-chemnitz.de>");
|
||||
MODULE_DESCRIPTION("X-Box pad driver");
|
||||
MODULE_DESCRIPTION("Xbox pad driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -866,7 +866,7 @@ static struct i2c_driver adp5588_driver = {
|
||||
.of_match_table = adp5588_of_match,
|
||||
.pm = pm_sleep_ptr(&adp5588_dev_pm_ops),
|
||||
},
|
||||
.probe_new = adp5588_probe,
|
||||
.probe = adp5588_probe,
|
||||
.remove = adp5588_remove,
|
||||
.id_table = adp5588_id,
|
||||
};
|
||||
|
@ -1054,7 +1054,7 @@ static struct i2c_driver adp5589_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.pm = pm_sleep_ptr(&adp5589_dev_pm_ops),
|
||||
},
|
||||
.probe_new = adp5589_probe,
|
||||
.probe = adp5589_probe,
|
||||
.id_table = adp5589_id,
|
||||
};
|
||||
|
||||
|
@ -309,12 +309,19 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
|
||||
return vivaldi_function_row_physmap_show(&atkbd->vdata, buf);
|
||||
}
|
||||
|
||||
static struct atkbd *atkbd_from_serio(struct serio *serio)
|
||||
{
|
||||
struct ps2dev *ps2dev = serio_get_drvdata(serio);
|
||||
|
||||
return container_of(ps2dev, struct atkbd, ps2dev);
|
||||
}
|
||||
|
||||
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int i)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
|
||||
if (attr == &atkbd_attr_function_row_physmap.attr &&
|
||||
!atkbd->vdata.num_function_row_keys)
|
||||
@ -392,46 +399,60 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code
|
||||
}
|
||||
|
||||
/*
|
||||
* atkbd_interrupt(). Here takes place processing of data received from
|
||||
* the keyboard into events.
|
||||
* Tries to handle frame or parity error by requesting the keyboard controller
|
||||
* to resend the last byte. This historically not done on x86 as controllers
|
||||
* there typically do not implement this command.
|
||||
*/
|
||||
|
||||
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||
unsigned int flags)
|
||||
static bool __maybe_unused atkbd_handle_frame_error(struct ps2dev *ps2dev,
|
||||
u8 data, unsigned int flags)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
|
||||
struct serio *serio = ps2dev->serio;
|
||||
|
||||
if ((flags & (SERIO_FRAME | SERIO_PARITY)) &&
|
||||
(~flags & SERIO_TIMEOUT) &&
|
||||
!atkbd->resend && atkbd->write) {
|
||||
dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
|
||||
serio_write(serio, ATKBD_CMD_RESEND);
|
||||
atkbd->resend = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!flags && data == ATKBD_RET_ACK)
|
||||
atkbd->resend = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum ps2_disposition atkbd_pre_receive_byte(struct ps2dev *ps2dev,
|
||||
u8 data, unsigned int flags)
|
||||
{
|
||||
struct serio *serio = ps2dev->serio;
|
||||
|
||||
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
|
||||
|
||||
#if !defined(__i386__) && !defined (__x86_64__)
|
||||
if (atkbd_handle_frame_error(ps2dev, data, flags))
|
||||
return PS2_IGNORE;
|
||||
#endif
|
||||
|
||||
return PS2_PROCESS;
|
||||
}
|
||||
|
||||
static void atkbd_receive_byte(struct ps2dev *ps2dev, u8 data)
|
||||
{
|
||||
struct serio *serio = ps2dev->serio;
|
||||
struct atkbd *atkbd = container_of(ps2dev, struct atkbd, ps2dev);
|
||||
struct input_dev *dev = atkbd->dev;
|
||||
unsigned int code = data;
|
||||
int scroll = 0, hscroll = 0, click = -1;
|
||||
int value;
|
||||
unsigned short keycode;
|
||||
|
||||
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
|
||||
|
||||
#if !defined(__i386__) && !defined (__x86_64__)
|
||||
if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
|
||||
dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
|
||||
serio_write(serio, ATKBD_CMD_RESEND);
|
||||
atkbd->resend = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!flags && data == ATKBD_RET_ACK)
|
||||
atkbd->resend = false;
|
||||
#endif
|
||||
|
||||
if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
|
||||
if (ps2_handle_ack(&atkbd->ps2dev, data))
|
||||
goto out;
|
||||
|
||||
if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD))
|
||||
if (ps2_handle_response(&atkbd->ps2dev, data))
|
||||
goto out;
|
||||
|
||||
pm_wakeup_event(&serio->dev, 0);
|
||||
|
||||
if (!atkbd->enabled)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
input_event(dev, EV_MSC, MSC_RAW, code);
|
||||
|
||||
@ -453,16 +474,16 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||
case ATKBD_RET_BAT:
|
||||
atkbd->enabled = false;
|
||||
serio_reconnect(atkbd->ps2dev.serio);
|
||||
goto out;
|
||||
return;
|
||||
case ATKBD_RET_EMUL0:
|
||||
atkbd->emul = 1;
|
||||
goto out;
|
||||
return;
|
||||
case ATKBD_RET_EMUL1:
|
||||
atkbd->emul = 2;
|
||||
goto out;
|
||||
return;
|
||||
case ATKBD_RET_RELEASE:
|
||||
atkbd->release = true;
|
||||
goto out;
|
||||
return;
|
||||
case ATKBD_RET_ACK:
|
||||
case ATKBD_RET_NAK:
|
||||
if (printk_ratelimit())
|
||||
@ -470,18 +491,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||
"Spurious %s on %s. "
|
||||
"Some program might be trying to access hardware directly.\n",
|
||||
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
|
||||
goto out;
|
||||
return;
|
||||
case ATKBD_RET_ERR:
|
||||
atkbd->err_count++;
|
||||
dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
|
||||
serio->phys);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
code = atkbd_compat_scancode(atkbd, code);
|
||||
|
||||
if (atkbd->emul && --atkbd->emul)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
keycode = atkbd->keycode[code];
|
||||
|
||||
@ -557,8 +578,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||
}
|
||||
|
||||
atkbd->release = false;
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int atkbd_set_repeat_rate(struct atkbd *atkbd)
|
||||
@ -909,7 +928,7 @@ static int atkbd_reset_state(struct atkbd *atkbd)
|
||||
|
||||
static void atkbd_cleanup(struct serio *serio)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
|
||||
atkbd_disable(atkbd);
|
||||
ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
|
||||
@ -922,7 +941,7 @@ static void atkbd_cleanup(struct serio *serio)
|
||||
|
||||
static void atkbd_disconnect(struct serio *serio)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
|
||||
atkbd_disable(atkbd);
|
||||
|
||||
@ -1188,7 +1207,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
|
||||
|
||||
static void atkbd_parse_fwnode_data(struct serio *serio)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
struct device *dev = &serio->dev;
|
||||
int n;
|
||||
|
||||
@ -1222,7 +1241,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
||||
goto fail1;
|
||||
|
||||
atkbd->dev = dev;
|
||||
ps2_init(&atkbd->ps2dev, serio);
|
||||
ps2_init(&atkbd->ps2dev, serio,
|
||||
atkbd_pre_receive_byte, atkbd_receive_byte);
|
||||
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
|
||||
mutex_init(&atkbd->mutex);
|
||||
|
||||
@ -1295,7 +1315,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
||||
|
||||
static int atkbd_reconnect(struct serio *serio)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
struct serio_driver *drv = serio->drv;
|
||||
int retval = -1;
|
||||
|
||||
@ -1378,7 +1398,7 @@ static struct serio_driver atkbd_drv = {
|
||||
},
|
||||
.description = DRIVER_DESC,
|
||||
.id_table = atkbd_serio_ids,
|
||||
.interrupt = atkbd_interrupt,
|
||||
.interrupt = ps2_interrupt,
|
||||
.connect = atkbd_connect,
|
||||
.reconnect = atkbd_reconnect,
|
||||
.disconnect = atkbd_disconnect,
|
||||
@ -1389,7 +1409,7 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
|
||||
ssize_t (*handler)(struct atkbd *, char *))
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
|
||||
return handler(atkbd, buf);
|
||||
}
|
||||
@ -1398,7 +1418,7 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t
|
||||
ssize_t (*handler)(struct atkbd *, const char *, size_t))
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct atkbd *atkbd = atkbd_from_serio(serio);
|
||||
int retval;
|
||||
|
||||
retval = mutex_lock_interruptible(&atkbd->mutex);
|
||||
|
@ -518,7 +518,7 @@ static struct i2c_driver cap11xx_i2c_driver = {
|
||||
.of_match_table = cap11xx_dt_ids,
|
||||
},
|
||||
.id_table = cap11xx_i2c_ids,
|
||||
.probe_new = cap11xx_i2c_probe,
|
||||
.probe = cap11xx_i2c_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(cap11xx_i2c_driver);
|
||||
|
@ -229,7 +229,7 @@ static struct i2c_driver cypress_sf_driver = {
|
||||
.of_match_table = of_match_ptr(cypress_sf_of_match),
|
||||
},
|
||||
.id_table = cypress_sf_id_table,
|
||||
.probe_new = cypress_sf_probe,
|
||||
.probe = cypress_sf_probe,
|
||||
};
|
||||
module_i2c_driver(cypress_sf_driver);
|
||||
|
||||
|
@ -145,7 +145,7 @@ static struct i2c_driver dir685_tk_i2c_driver = {
|
||||
.name = "dlink-dir685-touchkeys",
|
||||
.of_match_table = of_match_ptr(dir685_tk_of_match),
|
||||
},
|
||||
.probe_new = dir685_tk_probe,
|
||||
.probe = dir685_tk_probe,
|
||||
.id_table = dir685_tk_id,
|
||||
};
|
||||
module_i2c_driver(dir685_tk_i2c_driver);
|
||||
|
@ -456,7 +456,7 @@ static enum hrtimer_restart gpio_keys_irq_timer(struct hrtimer *t)
|
||||
struct input_dev *input = bdata->input;
|
||||
|
||||
if (bdata->key_pressed) {
|
||||
input_event(input, EV_KEY, *bdata->code, 0);
|
||||
input_report_key(input, *bdata->code, 0);
|
||||
input_sync(input);
|
||||
bdata->key_pressed = false;
|
||||
}
|
||||
@ -478,11 +478,11 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
|
||||
if (bdata->button->wakeup)
|
||||
pm_wakeup_event(bdata->input->dev.parent, 0);
|
||||
|
||||
input_event(input, EV_KEY, *bdata->code, 1);
|
||||
input_report_key(input, *bdata->code, 1);
|
||||
input_sync(input);
|
||||
|
||||
if (!bdata->release_delay) {
|
||||
input_event(input, EV_KEY, *bdata->code, 0);
|
||||
input_report_key(input, *bdata->code, 0);
|
||||
input_sync(input);
|
||||
goto out;
|
||||
}
|
||||
|
@ -826,7 +826,7 @@ static struct i2c_driver lm8323_i2c_driver = {
|
||||
.name = "lm8323",
|
||||
.pm = pm_sleep_ptr(&lm8323_pm_ops),
|
||||
},
|
||||
.probe_new = lm8323_probe,
|
||||
.probe = lm8323_probe,
|
||||
.remove = lm8323_remove,
|
||||
.id_table = lm8323_id,
|
||||
};
|
||||
|
@ -218,7 +218,7 @@ static struct i2c_driver lm8333_driver = {
|
||||
.driver = {
|
||||
.name = "lm8333",
|
||||
},
|
||||
.probe_new = lm8333_probe,
|
||||
.probe = lm8333_probe,
|
||||
.remove = lm8333_remove,
|
||||
.id_table = lm8333_id,
|
||||
};
|
||||
|
@ -280,7 +280,7 @@ static struct i2c_driver max7359_i2c_driver = {
|
||||
.name = "max7359",
|
||||
.pm = pm_sleep_ptr(&max7359_pm),
|
||||
},
|
||||
.probe_new = max7359_probe,
|
||||
.probe = max7359_probe,
|
||||
.id_table = max7359_ids,
|
||||
};
|
||||
|
||||
|
@ -258,7 +258,7 @@ static struct i2c_driver mcs_touchkey_driver = {
|
||||
.name = "mcs_touchkey",
|
||||
.pm = pm_sleep_ptr(&mcs_touchkey_pm_ops),
|
||||
},
|
||||
.probe_new = mcs_touchkey_probe,
|
||||
.probe = mcs_touchkey_probe,
|
||||
.remove = mcs_touchkey_remove,
|
||||
.shutdown = mcs_touchkey_shutdown,
|
||||
.id_table = mcs_touchkey_id,
|
||||
|
@ -389,7 +389,7 @@ static struct i2c_driver mpr_touchkey_driver = {
|
||||
.of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table),
|
||||
},
|
||||
.id_table = mpr121_id,
|
||||
.probe_new = mpr_touchkey_probe,
|
||||
.probe = mpr_touchkey_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(mpr_touchkey_driver);
|
||||
|
@ -455,7 +455,7 @@ static const struct of_device_id ppkb_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, ppkb_of_match);
|
||||
|
||||
static struct i2c_driver ppkb_driver = {
|
||||
.probe_new = ppkb_probe,
|
||||
.probe = ppkb_probe,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ppkb_of_match,
|
||||
|
@ -588,7 +588,7 @@ static struct i2c_driver qt1050_driver = {
|
||||
.of_match_table = of_match_ptr(qt1050_of_match),
|
||||
.pm = pm_sleep_ptr(&qt1050_pm_ops),
|
||||
},
|
||||
.probe_new = qt1050_probe,
|
||||
.probe = qt1050_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(qt1050_driver);
|
||||
|
@ -271,7 +271,7 @@ static struct i2c_driver qt1070_driver = {
|
||||
.pm = pm_sleep_ptr(&qt1070_pm_ops),
|
||||
},
|
||||
.id_table = qt1070_id,
|
||||
.probe_new = qt1070_probe,
|
||||
.probe = qt1070_probe,
|
||||
.remove = qt1070_remove,
|
||||
};
|
||||
|
||||
|
@ -460,7 +460,7 @@ static struct i2c_driver qt2160_driver = {
|
||||
},
|
||||
|
||||
.id_table = qt2160_idtable,
|
||||
.probe_new = qt2160_probe,
|
||||
.probe = qt2160_probe,
|
||||
.remove = qt2160_remove,
|
||||
};
|
||||
|
||||
|
@ -350,7 +350,7 @@ static struct i2c_driver tca6416_keypad_driver = {
|
||||
.name = "tca6416-keypad",
|
||||
.pm = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops),
|
||||
},
|
||||
.probe_new = tca6416_keypad_probe,
|
||||
.probe = tca6416_keypad_probe,
|
||||
.remove = tca6416_keypad_remove,
|
||||
.id_table = tca6416_id,
|
||||
};
|
||||
|
@ -370,7 +370,7 @@ static struct i2c_driver tca8418_keypad_driver = {
|
||||
.name = "tca8418_keypad",
|
||||
.of_match_table = tca8418_dt_ids,
|
||||
},
|
||||
.probe_new = tca8418_keypad_probe,
|
||||
.probe = tca8418_keypad_probe,
|
||||
.id_table = tca8418_id,
|
||||
};
|
||||
|
||||
|
@ -356,7 +356,7 @@ static struct i2c_driver tm2_touchkey_driver = {
|
||||
.pm = pm_sleep_ptr(&tm2_touchkey_pm_ops),
|
||||
.of_match_table = tm2_touchkey_of_match,
|
||||
},
|
||||
.probe_new = tm2_touchkey_probe,
|
||||
.probe = tm2_touchkey_probe,
|
||||
.id_table = tm2_touchkey_id_table,
|
||||
};
|
||||
module_i2c_driver(tm2_touchkey_driver);
|
||||
|
@ -86,7 +86,7 @@ static struct i2c_driver ad714x_i2c_driver = {
|
||||
.name = "ad714x_captouch",
|
||||
.pm = pm_sleep_ptr(&ad714x_pm),
|
||||
},
|
||||
.probe_new = ad714x_i2c_probe,
|
||||
.probe = ad714x_i2c_probe,
|
||||
.id_table = ad714x_id,
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,7 @@ static struct i2c_driver adxl34x_driver = {
|
||||
.pm = pm_sleep_ptr(&adxl34x_pm),
|
||||
.of_match_table = adxl34x_of_id,
|
||||
},
|
||||
.probe_new = adxl34x_i2c_probe,
|
||||
.probe = adxl34x_i2c_probe,
|
||||
.remove = adxl34x_i2c_remove,
|
||||
.id_table = adxl34x_id,
|
||||
};
|
||||
|
@ -817,8 +817,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
|
||||
AC_WRITE(ac, POWER_CTL, 0);
|
||||
|
||||
err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
|
||||
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
|
||||
dev_name(dev), ac);
|
||||
IRQF_ONESHOT, dev_name(dev), ac);
|
||||
if (err) {
|
||||
dev_err(dev, "irq %d busy?\n", ac->irq);
|
||||
goto err_free_mem;
|
||||
|
@ -201,7 +201,7 @@ static struct i2c_driver apanel_driver = {
|
||||
.driver = {
|
||||
.name = APANEL,
|
||||
},
|
||||
.probe_new = apanel_probe,
|
||||
.probe = apanel_probe,
|
||||
.shutdown = apanel_shutdown,
|
||||
.id_table = apanel_id,
|
||||
};
|
||||
|
@ -263,7 +263,7 @@ static const struct i2c_device_id atmel_captouch_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
|
||||
|
||||
static struct i2c_driver atmel_captouch_driver = {
|
||||
.probe_new = atmel_captouch_probe,
|
||||
.probe = atmel_captouch_probe,
|
||||
.id_table = atmel_captouch_id,
|
||||
.driver = {
|
||||
.name = "atmel_captouch",
|
||||
|
@ -551,7 +551,7 @@ static struct i2c_driver bma150_driver = {
|
||||
},
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.id_table = bma150_id,
|
||||
.probe_new = bma150_probe,
|
||||
.probe = bma150_probe,
|
||||
.remove = bma150_remove,
|
||||
};
|
||||
|
||||
|
@ -97,7 +97,7 @@ static const struct i2c_device_id cma3000_i2c_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
|
||||
|
||||
static struct i2c_driver cma3000_i2c_driver = {
|
||||
.probe_new = cma3000_i2c_probe,
|
||||
.probe = cma3000_i2c_probe,
|
||||
.remove = cma3000_i2c_remove,
|
||||
.id_table = cma3000_i2c_id,
|
||||
.driver = {
|
||||
|
@ -1321,7 +1321,7 @@ static struct i2c_driver da7280_driver = {
|
||||
.of_match_table = of_match_ptr(da7280_of_match),
|
||||
.pm = pm_sleep_ptr(&da7280_pm_ops),
|
||||
},
|
||||
.probe_new = da7280_probe,
|
||||
.probe = da7280_probe,
|
||||
.id_table = da7280_i2c_id,
|
||||
};
|
||||
module_i2c_driver(da7280_driver);
|
||||
|
@ -149,7 +149,7 @@
|
||||
|
||||
/* Control 3 Register */
|
||||
#define DRV260X_LRA_OPEN_LOOP (1 << 0)
|
||||
#define DRV260X_ANANLOG_IN (1 << 1)
|
||||
#define DRV260X_ANALOG_IN (1 << 1)
|
||||
#define DRV260X_LRA_DRV_MODE (1 << 2)
|
||||
#define DRV260X_RTP_UNSIGNED_DATA (1 << 3)
|
||||
#define DRV260X_SUPPLY_COMP_DIS (1 << 4)
|
||||
@ -186,51 +186,13 @@ struct drv260x_data {
|
||||
struct work_struct work;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *regulator;
|
||||
u32 magnitude;
|
||||
u8 magnitude;
|
||||
u32 mode;
|
||||
u32 library;
|
||||
int rated_voltage;
|
||||
int overdrive_voltage;
|
||||
};
|
||||
|
||||
static const struct reg_default drv260x_reg_defs[] = {
|
||||
{ DRV260X_STATUS, 0xe0 },
|
||||
{ DRV260X_MODE, 0x40 },
|
||||
{ DRV260X_RT_PB_IN, 0x00 },
|
||||
{ DRV260X_LIB_SEL, 0x00 },
|
||||
{ DRV260X_WV_SEQ_1, 0x01 },
|
||||
{ DRV260X_WV_SEQ_2, 0x00 },
|
||||
{ DRV260X_WV_SEQ_3, 0x00 },
|
||||
{ DRV260X_WV_SEQ_4, 0x00 },
|
||||
{ DRV260X_WV_SEQ_5, 0x00 },
|
||||
{ DRV260X_WV_SEQ_6, 0x00 },
|
||||
{ DRV260X_WV_SEQ_7, 0x00 },
|
||||
{ DRV260X_WV_SEQ_8, 0x00 },
|
||||
{ DRV260X_GO, 0x00 },
|
||||
{ DRV260X_OVERDRIVE_OFF, 0x00 },
|
||||
{ DRV260X_SUSTAIN_P_OFF, 0x00 },
|
||||
{ DRV260X_SUSTAIN_N_OFF, 0x00 },
|
||||
{ DRV260X_BRAKE_OFF, 0x00 },
|
||||
{ DRV260X_A_TO_V_CTRL, 0x05 },
|
||||
{ DRV260X_A_TO_V_MIN_INPUT, 0x19 },
|
||||
{ DRV260X_A_TO_V_MAX_INPUT, 0xff },
|
||||
{ DRV260X_A_TO_V_MIN_OUT, 0x19 },
|
||||
{ DRV260X_A_TO_V_MAX_OUT, 0xff },
|
||||
{ DRV260X_RATED_VOLT, 0x3e },
|
||||
{ DRV260X_OD_CLAMP_VOLT, 0x8c },
|
||||
{ DRV260X_CAL_COMP, 0x0c },
|
||||
{ DRV260X_CAL_BACK_EMF, 0x6c },
|
||||
{ DRV260X_FEEDBACK_CTRL, 0x36 },
|
||||
{ DRV260X_CTRL1, 0x93 },
|
||||
{ DRV260X_CTRL2, 0xfa },
|
||||
{ DRV260X_CTRL3, 0xa0 },
|
||||
{ DRV260X_CTRL4, 0x20 },
|
||||
{ DRV260X_CTRL5, 0x80 },
|
||||
{ DRV260X_LRA_LOOP_PERIOD, 0x33 },
|
||||
{ DRV260X_VBAT_MON, 0x00 },
|
||||
{ DRV260X_LRA_RES_PERIOD, 0x00 },
|
||||
};
|
||||
|
||||
#define DRV260X_DEF_RATED_VOLT 0x90
|
||||
#define DRV260X_DEF_OD_CLAMP_VOLT 0x90
|
||||
|
||||
@ -275,10 +237,11 @@ static int drv260x_haptics_play(struct input_dev *input, void *data,
|
||||
|
||||
haptics->mode = DRV260X_LRA_NO_CAL_MODE;
|
||||
|
||||
/* Scale u16 magnitude into u8 register value */
|
||||
if (effect->u.rumble.strong_magnitude > 0)
|
||||
haptics->magnitude = effect->u.rumble.strong_magnitude;
|
||||
haptics->magnitude = effect->u.rumble.strong_magnitude >> 8;
|
||||
else if (effect->u.rumble.weak_magnitude > 0)
|
||||
haptics->magnitude = effect->u.rumble.weak_magnitude;
|
||||
haptics->magnitude = effect->u.rumble.weak_magnitude >> 8;
|
||||
else
|
||||
haptics->magnitude = 0;
|
||||
|
||||
@ -304,7 +267,7 @@ static void drv260x_close(struct input_dev *input)
|
||||
|
||||
static const struct reg_sequence drv260x_lra_cal_regs[] = {
|
||||
{ DRV260X_MODE, DRV260X_AUTO_CAL },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA },
|
||||
{ DRV260X_FEEDBACK_CTRL, DRV260X_FB_REG_LRA_MODE |
|
||||
DRV260X_BRAKE_FACTOR_4X | DRV260X_LOOP_GAIN_HIGH },
|
||||
};
|
||||
@ -322,7 +285,7 @@ static const struct reg_sequence drv260x_lra_init_regs[] = {
|
||||
DRV260X_BEMF_GAIN_3 },
|
||||
{ DRV260X_CTRL1, DRV260X_STARTUP_BOOST },
|
||||
{ DRV260X_CTRL2, DRV260X_SAMP_TIME_250 },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ANANLOG_IN },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA | DRV260X_ANALOG_IN },
|
||||
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
|
||||
};
|
||||
|
||||
@ -337,7 +300,7 @@ static const struct reg_sequence drv260x_erm_cal_regs[] = {
|
||||
{ DRV260X_CTRL1, DRV260X_STARTUP_BOOST },
|
||||
{ DRV260X_CTRL2, DRV260X_SAMP_TIME_250 | DRV260X_BLANK_TIME_75 |
|
||||
DRV260X_IDISS_TIME_75 },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_ERM_OPEN_LOOP },
|
||||
{ DRV260X_CTRL3, DRV260X_NG_THRESH_2 | DRV260X_RTP_UNSIGNED_DATA },
|
||||
{ DRV260X_CTRL4, DRV260X_AUTOCAL_TIME_500MS },
|
||||
};
|
||||
|
||||
@ -435,6 +398,7 @@ static int drv260x_init(struct drv260x_data *haptics)
|
||||
}
|
||||
|
||||
do {
|
||||
usleep_range(15000, 15500);
|
||||
error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf);
|
||||
if (error) {
|
||||
dev_err(&haptics->client->dev,
|
||||
@ -452,8 +416,6 @@ static const struct regmap_config drv260x_regmap_config = {
|
||||
.val_bits = 8,
|
||||
|
||||
.max_register = DRV260X_MAX_REG,
|
||||
.reg_defaults = drv260x_reg_defs,
|
||||
.num_reg_defaults = ARRAY_SIZE(drv260x_reg_defs),
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
||||
@ -653,7 +615,7 @@ static const struct of_device_id drv260x_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, drv260x_of_match);
|
||||
|
||||
static struct i2c_driver drv260x_driver = {
|
||||
.probe_new = drv260x_probe,
|
||||
.probe = drv260x_probe,
|
||||
.driver = {
|
||||
.name = "drv260x-haptics",
|
||||
.of_match_table = drv260x_of_match,
|
||||
|
@ -297,7 +297,7 @@ MODULE_DEVICE_TABLE(of, drv2665_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver drv2665_driver = {
|
||||
.probe_new = drv2665_probe,
|
||||
.probe = drv2665_probe,
|
||||
.driver = {
|
||||
.name = "drv2665-haptics",
|
||||
.of_match_table = of_match_ptr(drv2665_of_match),
|
||||
|
@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, drv2667_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver drv2667_driver = {
|
||||
.probe_new = drv2667_probe,
|
||||
.probe = drv2667_probe,
|
||||
.driver = {
|
||||
.name = "drv2667-haptics",
|
||||
.of_match_table = of_match_ptr(drv2667_of_match),
|
||||
|
@ -189,7 +189,7 @@ static struct i2c_driver ibm_panel_driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.of_match_table = ibm_panel_match,
|
||||
},
|
||||
.probe_new = ibm_panel_probe,
|
||||
.probe = ibm_panel_probe,
|
||||
.remove = ibm_panel_remove,
|
||||
};
|
||||
module_i2c_driver(ibm_panel_driver);
|
||||
|
@ -1746,7 +1746,7 @@ static struct i2c_driver iqs269_i2c_driver = {
|
||||
.of_match_table = iqs269_of_match,
|
||||
.pm = pm_sleep_ptr(&iqs269_pm),
|
||||
},
|
||||
.probe_new = iqs269_probe,
|
||||
.probe = iqs269_probe,
|
||||
};
|
||||
module_i2c_driver(iqs269_i2c_driver);
|
||||
|
||||
|
@ -1822,7 +1822,7 @@ static struct i2c_driver iqs626_i2c_driver = {
|
||||
.of_match_table = iqs626_of_match,
|
||||
.pm = pm_sleep_ptr(&iqs626_pm),
|
||||
},
|
||||
.probe_new = iqs626_probe,
|
||||
.probe = iqs626_probe,
|
||||
};
|
||||
module_i2c_driver(iqs626_i2c_driver);
|
||||
|
||||
|
@ -2593,7 +2593,7 @@ static struct i2c_driver iqs7222_i2c_driver = {
|
||||
.name = "iqs7222",
|
||||
.of_match_table = iqs7222_of_match,
|
||||
},
|
||||
.probe_new = iqs7222_probe,
|
||||
.probe = iqs7222_probe,
|
||||
};
|
||||
module_i2c_driver(iqs7222_i2c_driver);
|
||||
|
||||
|
@ -538,7 +538,7 @@ static struct i2c_driver kxtj9_driver = {
|
||||
.name = NAME,
|
||||
.pm = pm_sleep_ptr(&kxtj9_pm_ops),
|
||||
},
|
||||
.probe_new = kxtj9_probe,
|
||||
.probe = kxtj9_probe,
|
||||
.id_table = kxtj9_id,
|
||||
};
|
||||
|
||||
|
@ -202,7 +202,7 @@ static struct i2c_driver mma8450_driver = {
|
||||
.name = MMA8450_DRV_NAME,
|
||||
.of_match_table = mma8450_dt_ids,
|
||||
},
|
||||
.probe_new = mma8450_probe,
|
||||
.probe = mma8450_probe,
|
||||
.id_table = mma8450_id,
|
||||
};
|
||||
|
||||
|
@ -199,7 +199,7 @@ static struct i2c_driver pcf8574_kp_driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = pm_sleep_ptr(&pcf8574_kp_pm_ops),
|
||||
},
|
||||
.probe_new = pcf8574_kp_probe,
|
||||
.probe = pcf8574_kp_probe,
|
||||
.remove = pcf8574_kp_remove,
|
||||
.id_table = pcf8574_kp_id,
|
||||
};
|
||||
|
@ -50,7 +50,10 @@
|
||||
#define PON_RESIN_PULL_UP BIT(0)
|
||||
|
||||
#define PON_DBC_CTL 0x71
|
||||
#define PON_DBC_DELAY_MASK 0x7
|
||||
#define PON_DBC_DELAY_MASK_GEN1 0x7
|
||||
#define PON_DBC_DELAY_MASK_GEN2 0xf
|
||||
#define PON_DBC_SHIFT_GEN1 6
|
||||
#define PON_DBC_SHIFT_GEN2 14
|
||||
|
||||
struct pm8941_data {
|
||||
unsigned int pull_up_bit;
|
||||
@ -247,7 +250,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
||||
struct device *parent;
|
||||
struct device_node *regmap_node;
|
||||
const __be32 *addr;
|
||||
u32 req_delay;
|
||||
u32 req_delay, mask, delay_shift;
|
||||
int error;
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay))
|
||||
@ -336,12 +339,20 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
|
||||
pwrkey->input->phys = pwrkey->data->phys;
|
||||
|
||||
if (pwrkey->data->supports_debounce_config) {
|
||||
req_delay = (req_delay << 6) / USEC_PER_SEC;
|
||||
if (pwrkey->subtype >= PON_SUBTYPE_GEN2_PRIMARY) {
|
||||
mask = PON_DBC_DELAY_MASK_GEN2;
|
||||
delay_shift = PON_DBC_SHIFT_GEN2;
|
||||
} else {
|
||||
mask = PON_DBC_DELAY_MASK_GEN1;
|
||||
delay_shift = PON_DBC_SHIFT_GEN1;
|
||||
}
|
||||
|
||||
req_delay = (req_delay << delay_shift) / USEC_PER_SEC;
|
||||
req_delay = ilog2(req_delay);
|
||||
|
||||
error = regmap_update_bits(pwrkey->regmap,
|
||||
pwrkey->baseaddr + PON_DBC_CTL,
|
||||
PON_DBC_DELAY_MASK,
|
||||
mask,
|
||||
req_delay);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to set debounce: %d\n",
|
||||
|
@ -11,6 +11,7 @@
|
||||
* Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -23,6 +24,7 @@
|
||||
|
||||
struct pwm_vibrator {
|
||||
struct input_dev *input;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct pwm_device *pwm;
|
||||
struct pwm_device *pwm_dir;
|
||||
struct regulator *vcc;
|
||||
@ -42,19 +44,21 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
|
||||
if (!vibrator->vcc_on) {
|
||||
err = regulator_enable(vibrator->vcc);
|
||||
if (err) {
|
||||
dev_err(pdev, "failed to enable regulator: %d", err);
|
||||
dev_err(pdev, "failed to enable regulator: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
vibrator->vcc_on = true;
|
||||
}
|
||||
|
||||
gpiod_set_value_cansleep(vibrator->enable_gpio, 1);
|
||||
|
||||
pwm_get_state(vibrator->pwm, &state);
|
||||
pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff);
|
||||
state.enabled = true;
|
||||
|
||||
err = pwm_apply_state(vibrator->pwm, &state);
|
||||
if (err) {
|
||||
dev_err(pdev, "failed to apply pwm state: %d", err);
|
||||
dev_err(pdev, "failed to apply pwm state: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -65,7 +69,7 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
|
||||
|
||||
err = pwm_apply_state(vibrator->pwm_dir, &state);
|
||||
if (err) {
|
||||
dev_err(pdev, "failed to apply dir-pwm state: %d", err);
|
||||
dev_err(pdev, "failed to apply dir-pwm state: %d\n", err);
|
||||
pwm_disable(vibrator->pwm);
|
||||
return err;
|
||||
}
|
||||
@ -80,6 +84,8 @@ static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
|
||||
pwm_disable(vibrator->pwm_dir);
|
||||
pwm_disable(vibrator->pwm);
|
||||
|
||||
gpiod_set_value_cansleep(vibrator->enable_gpio, 0);
|
||||
|
||||
if (vibrator->vcc_on) {
|
||||
regulator_disable(vibrator->vcc);
|
||||
vibrator->vcc_on = false;
|
||||
@ -137,7 +143,17 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
err = PTR_ERR_OR_ZERO(vibrator->vcc);
|
||||
if (err) {
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to request regulator: %d",
|
||||
dev_err(&pdev->dev, "Failed to request regulator: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
|
||||
vibrator->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
|
||||
GPIOD_OUT_LOW);
|
||||
err = PTR_ERR_OR_ZERO(vibrator->enable_gpio);
|
||||
if (err) {
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to request enable gpio: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
@ -146,7 +162,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
err = PTR_ERR_OR_ZERO(vibrator->pwm);
|
||||
if (err) {
|
||||
if (err != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "Failed to request main pwm: %d",
|
||||
dev_err(&pdev->dev, "Failed to request main pwm: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
@ -158,7 +174,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
state.enabled = false;
|
||||
err = pwm_apply_state(vibrator->pwm, &state);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
|
||||
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
@ -172,7 +188,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
state.enabled = false;
|
||||
err = pwm_apply_state(vibrator->pwm_dir, &state);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to apply initial PWM state: %d",
|
||||
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
@ -189,7 +205,7 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&pdev->dev, "Failed to request direction pwm: %d", err);
|
||||
dev_err(&pdev->dev, "Failed to request direction pwm: %d\n", err);
|
||||
fallthrough;
|
||||
|
||||
case -EPROBE_DEFER:
|
||||
@ -207,13 +223,13 @@ static int pwm_vibrator_probe(struct platform_device *pdev)
|
||||
err = input_ff_create_memless(vibrator->input, NULL,
|
||||
pwm_vibrator_play_effect);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Couldn't create FF dev: %d", err);
|
||||
dev_err(&pdev->dev, "Couldn't create FF dev: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_register_device(vibrator->input);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Couldn't register input dev: %d", err);
|
||||
dev_err(&pdev->dev, "Couldn't register input dev: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -117,14 +117,16 @@ static int tps65219_pb_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65219_pb_remove(struct platform_device *pdev)
|
||||
static void tps65219_pb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
/* Disable interrupt for the pushbutton */
|
||||
return regmap_update_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
|
||||
TPS65219_REG_MASK_INT_FOR_PB_MASK,
|
||||
TPS65219_REG_MASK_INT_FOR_PB_MASK);
|
||||
ret = regmap_set_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
|
||||
TPS65219_REG_MASK_INT_FOR_PB_MASK);
|
||||
if (ret)
|
||||
dev_warn(&pdev->dev, "Failed to disable irq (%pe)\n", ERR_PTR(ret));
|
||||
}
|
||||
|
||||
static const struct platform_device_id tps65219_pwrbtn_id_table[] = {
|
||||
@ -135,7 +137,7 @@ MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table);
|
||||
|
||||
static struct platform_driver tps65219_pb_driver = {
|
||||
.probe = tps65219_pb_probe,
|
||||
.remove = tps65219_pb_remove,
|
||||
.remove_new = tps65219_pb_remove,
|
||||
.driver = {
|
||||
.name = "tps65219_pwrbutton",
|
||||
},
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define UINPUT_NAME "uinput"
|
||||
#define UINPUT_BUFFER_SIZE 16
|
||||
#define UINPUT_NUM_REQUESTS 16
|
||||
#define UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS 10
|
||||
|
||||
enum uinput_state { UIST_NEW_DEVICE, UIST_SETUP_COMPLETE, UIST_CREATED };
|
||||
|
||||
@ -569,11 +570,40 @@ static int uinput_setup_device_legacy(struct uinput_device *udev,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the given timestamp is valid (i.e., if all the following
|
||||
* conditions are satisfied), false otherwise.
|
||||
* 1) given timestamp is positive
|
||||
* 2) it's within the allowed offset before the current time
|
||||
* 3) it's not in the future
|
||||
*/
|
||||
static bool is_valid_timestamp(const ktime_t timestamp)
|
||||
{
|
||||
ktime_t zero_time;
|
||||
ktime_t current_time;
|
||||
ktime_t min_time;
|
||||
ktime_t offset;
|
||||
|
||||
zero_time = ktime_set(0, 0);
|
||||
if (ktime_compare(zero_time, timestamp) >= 0)
|
||||
return false;
|
||||
|
||||
current_time = ktime_get();
|
||||
offset = ktime_set(UINPUT_TIMESTAMP_ALLOWED_OFFSET_SECS, 0);
|
||||
min_time = ktime_sub(current_time, offset);
|
||||
|
||||
if (ktime_after(min_time, timestamp) || ktime_after(timestamp, current_time))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static ssize_t uinput_inject_events(struct uinput_device *udev,
|
||||
const char __user *buffer, size_t count)
|
||||
{
|
||||
struct input_event ev;
|
||||
size_t bytes = 0;
|
||||
ktime_t timestamp;
|
||||
|
||||
if (count != 0 && count < input_event_size())
|
||||
return -EINVAL;
|
||||
@ -588,6 +618,10 @@ static ssize_t uinput_inject_events(struct uinput_device *udev,
|
||||
if (input_event_from_user(buffer + bytes, &ev))
|
||||
return -EFAULT;
|
||||
|
||||
timestamp = ktime_set(ev.input_event_sec, ev.input_event_usec * NSEC_PER_USEC);
|
||||
if (is_valid_timestamp(timestamp))
|
||||
input_set_timestamp(udev->dev, timestamp);
|
||||
|
||||
input_event(udev->dev, ev.type, ev.code, ev.value);
|
||||
bytes += input_event_size();
|
||||
cond_resched();
|
||||
|
@ -1489,7 +1489,7 @@ static struct i2c_driver cyapa_driver = {
|
||||
.of_match_table = of_match_ptr(cyapa_of_match),
|
||||
},
|
||||
|
||||
.probe_new = cyapa_probe,
|
||||
.probe = cyapa_probe,
|
||||
.id_table = cyapa_id_table,
|
||||
};
|
||||
|
||||
|
@ -1424,7 +1424,7 @@ static struct i2c_driver elan_driver = {
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
.dev_groups = elan_sysfs_groups,
|
||||
},
|
||||
.probe_new = elan_probe,
|
||||
.probe = elan_probe,
|
||||
.id_table = elan_id,
|
||||
};
|
||||
|
||||
|
@ -116,6 +116,13 @@ static DEFINE_MUTEX(psmouse_mutex);
|
||||
|
||||
static struct workqueue_struct *kpsmoused_wq;
|
||||
|
||||
struct psmouse *psmouse_from_serio(struct serio *serio)
|
||||
{
|
||||
struct ps2dev *ps2dev = serio_get_drvdata(serio);
|
||||
|
||||
return container_of(ps2dev, struct psmouse, ps2dev);
|
||||
}
|
||||
|
||||
void psmouse_report_standard_buttons(struct input_dev *dev, u8 buttons)
|
||||
{
|
||||
input_report_key(dev, BTN_LEFT, buttons & BIT(0));
|
||||
@ -329,17 +336,14 @@ static void psmouse_handle_oob_data(struct psmouse *psmouse, u8 data)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* psmouse_interrupt() handles incoming characters, either passing them
|
||||
* for normal processing or gathering them as command response.
|
||||
*/
|
||||
static irqreturn_t psmouse_interrupt(struct serio *serio,
|
||||
u8 data, unsigned int flags)
|
||||
static enum ps2_disposition psmouse_pre_receive_byte(struct ps2dev *ps2dev,
|
||||
u8 data,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
|
||||
|
||||
if (psmouse->state == PSMOUSE_IGNORE)
|
||||
goto out;
|
||||
return PS2_IGNORE;
|
||||
|
||||
if (unlikely((flags & SERIO_TIMEOUT) ||
|
||||
((flags & SERIO_PARITY) &&
|
||||
@ -350,27 +354,25 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
|
||||
"bad data from KBC -%s%s\n",
|
||||
flags & SERIO_TIMEOUT ? " timeout" : "",
|
||||
flags & SERIO_PARITY ? " bad parity" : "");
|
||||
ps2_cmd_aborted(&psmouse->ps2dev);
|
||||
goto out;
|
||||
return PS2_ERROR;
|
||||
}
|
||||
|
||||
if (flags & SERIO_OOB_DATA) {
|
||||
psmouse_handle_oob_data(psmouse, data);
|
||||
goto out;
|
||||
return PS2_IGNORE;
|
||||
}
|
||||
|
||||
if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_ACK))
|
||||
if (ps2_handle_ack(&psmouse->ps2dev, data))
|
||||
goto out;
|
||||
return PS2_PROCESS;
|
||||
}
|
||||
|
||||
if (unlikely(psmouse->ps2dev.flags & PS2_FLAG_CMD))
|
||||
if (ps2_handle_response(&psmouse->ps2dev, data))
|
||||
goto out;
|
||||
static void psmouse_receive_byte(struct ps2dev *ps2dev, u8 data)
|
||||
{
|
||||
struct psmouse *psmouse = container_of(ps2dev, struct psmouse, ps2dev);
|
||||
|
||||
pm_wakeup_event(&serio->dev, 0);
|
||||
pm_wakeup_event(&ps2dev->serio->dev, 0);
|
||||
|
||||
if (psmouse->state <= PSMOUSE_RESYNCING)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (psmouse->state == PSMOUSE_ACTIVATED &&
|
||||
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
|
||||
@ -379,7 +381,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
|
||||
psmouse->badbyte = psmouse->packet[0];
|
||||
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
|
||||
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
psmouse->packet[psmouse->pktcnt++] = data;
|
||||
@ -388,21 +390,21 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
|
||||
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
|
||||
if (psmouse->pktcnt == 1) {
|
||||
psmouse->last = jiffies;
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
if (psmouse->packet[1] == PSMOUSE_RET_ID ||
|
||||
(psmouse->protocol->type == PSMOUSE_HGPK &&
|
||||
psmouse->packet[1] == PSMOUSE_RET_BAT)) {
|
||||
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
|
||||
serio_reconnect(serio);
|
||||
goto out;
|
||||
serio_reconnect(ps2dev->serio);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Not a new device, try processing first byte normally */
|
||||
psmouse->pktcnt = 1;
|
||||
if (psmouse_handle_byte(psmouse))
|
||||
goto out;
|
||||
return;
|
||||
|
||||
psmouse->packet[psmouse->pktcnt++] = data;
|
||||
}
|
||||
@ -417,14 +419,11 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
|
||||
psmouse->badbyte = psmouse->packet[0];
|
||||
__psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
|
||||
psmouse_queue_work(psmouse, &psmouse->resync_work, 0);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
psmouse->last = jiffies;
|
||||
psmouse_handle_byte(psmouse);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1344,7 +1343,7 @@ static void psmouse_resync(struct work_struct *work)
|
||||
goto out;
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1428,13 +1427,13 @@ static void psmouse_resync(struct work_struct *work)
|
||||
*/
|
||||
static void psmouse_cleanup(struct serio *serio)
|
||||
{
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = psmouse_from_serio(serio);
|
||||
struct psmouse *parent = NULL;
|
||||
|
||||
mutex_lock(&psmouse_mutex);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1476,7 +1475,7 @@ static void psmouse_cleanup(struct serio *serio)
|
||||
*/
|
||||
static void psmouse_disconnect(struct serio *serio)
|
||||
{
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = psmouse_from_serio(serio);
|
||||
struct psmouse *parent = NULL;
|
||||
|
||||
mutex_lock(&psmouse_mutex);
|
||||
@ -1489,7 +1488,7 @@ static void psmouse_disconnect(struct serio *serio)
|
||||
mutex_lock(&psmouse_mutex);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1588,7 +1587,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
* connected to this port can be successfully identified
|
||||
*/
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1597,15 +1596,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
if (!psmouse || !input_dev)
|
||||
goto err_free;
|
||||
|
||||
ps2_init(&psmouse->ps2dev, serio);
|
||||
ps2_init(&psmouse->ps2dev, serio,
|
||||
psmouse_pre_receive_byte, psmouse_receive_byte);
|
||||
INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync);
|
||||
psmouse->dev = input_dev;
|
||||
snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
|
||||
|
||||
serio_set_drvdata(serio, psmouse);
|
||||
|
||||
error = serio_open(serio, drv);
|
||||
if (error)
|
||||
goto err_clear_drvdata;
|
||||
@ -1676,7 +1674,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
|
||||
static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
|
||||
{
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = psmouse_from_serio(serio);
|
||||
struct psmouse *parent = NULL;
|
||||
int (*reconnect_handler)(struct psmouse *);
|
||||
enum psmouse_type type;
|
||||
@ -1695,7 +1693,7 @@ static int __psmouse_reconnect(struct serio *serio, bool fast_reconnect)
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1781,7 +1779,7 @@ static struct serio_driver psmouse_drv = {
|
||||
},
|
||||
.description = DRIVER_DESC,
|
||||
.id_table = psmouse_serio_ids,
|
||||
.interrupt = psmouse_interrupt,
|
||||
.interrupt = ps2_interrupt,
|
||||
.connect = psmouse_connect,
|
||||
.reconnect = psmouse_reconnect,
|
||||
.fast_reconnect = psmouse_fast_reconnect,
|
||||
@ -1794,7 +1792,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct psmouse_attribute *attr = to_psmouse_attr(devattr);
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = psmouse_from_serio(serio);
|
||||
|
||||
if (psmouse->protocol->smbus_companion &&
|
||||
devattr != &psmouse_attr_protocol.dattr)
|
||||
@ -1815,7 +1813,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
psmouse = psmouse_from_serio(serio);
|
||||
|
||||
if (psmouse->protocol->smbus_companion &&
|
||||
devattr != &psmouse_attr_protocol.dattr) {
|
||||
@ -1830,7 +1828,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
@ -1925,7 +1923,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
parent = psmouse_from_serio(serio->parent);
|
||||
if (parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
}
|
||||
|
@ -130,6 +130,8 @@ struct psmouse {
|
||||
void (*pt_deactivate)(struct psmouse *psmouse);
|
||||
};
|
||||
|
||||
struct psmouse *psmouse_from_serio(struct serio *serio);
|
||||
|
||||
void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work,
|
||||
unsigned long delay);
|
||||
int psmouse_reset(struct psmouse *psmouse);
|
||||
|
@ -628,7 +628,7 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
|
||||
****************************************************************************/
|
||||
static int synaptics_pt_write(struct serio *serio, u8 c)
|
||||
{
|
||||
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
||||
struct psmouse *parent = psmouse_from_serio(serio->parent);
|
||||
u8 rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
|
||||
int error;
|
||||
|
||||
@ -645,7 +645,7 @@ static int synaptics_pt_write(struct serio *serio, u8 c)
|
||||
|
||||
static int synaptics_pt_start(struct serio *serio)
|
||||
{
|
||||
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
||||
struct psmouse *parent = psmouse_from_serio(serio->parent);
|
||||
struct synaptics_data *priv = parent->private;
|
||||
|
||||
serio_pause_rx(parent->ps2dev.serio);
|
||||
@ -657,7 +657,7 @@ static int synaptics_pt_start(struct serio *serio)
|
||||
|
||||
static void synaptics_pt_stop(struct serio *serio)
|
||||
{
|
||||
struct psmouse *parent = serio_get_drvdata(serio->parent);
|
||||
struct psmouse *parent = psmouse_from_serio(serio->parent);
|
||||
struct synaptics_data *priv = parent->private;
|
||||
|
||||
serio_pause_rx(parent->ps2dev.serio);
|
||||
@ -672,7 +672,7 @@ static int synaptics_is_pt_packet(u8 *buf)
|
||||
|
||||
static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet)
|
||||
{
|
||||
struct psmouse *child = serio_get_drvdata(ptport);
|
||||
struct psmouse *child = psmouse_from_serio(ptport);
|
||||
|
||||
if (child && child->state == PSMOUSE_ACTIVATED) {
|
||||
serio_interrupt(ptport, packet[1], 0);
|
||||
@ -688,7 +688,7 @@ static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet)
|
||||
static void synaptics_pt_activate(struct psmouse *psmouse)
|
||||
{
|
||||
struct synaptics_data *priv = psmouse->private;
|
||||
struct psmouse *child = serio_get_drvdata(priv->pt_port);
|
||||
struct psmouse *child = psmouse_from_serio(priv->pt_port);
|
||||
|
||||
/* adjust the touchpad to child's choice of protocol */
|
||||
if (child) {
|
||||
|
@ -650,7 +650,7 @@ static struct i2c_driver synaptics_i2c_driver = {
|
||||
.pm = pm_sleep_ptr(&synaptics_i2c_pm),
|
||||
},
|
||||
|
||||
.probe_new = synaptics_i2c_probe,
|
||||
.probe = synaptics_i2c_probe,
|
||||
.remove = synaptics_i2c_remove,
|
||||
|
||||
.id_table = synaptics_i2c_id_table,
|
||||
|
@ -216,7 +216,7 @@ static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct psmouse *psmouse = serio_get_drvdata(serio);
|
||||
struct psmouse *psmouse = psmouse_from_serio(serio);
|
||||
|
||||
return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0;
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ static struct i2c_driver rmi_i2c_driver = {
|
||||
.of_match_table = of_match_ptr(rmi_i2c_of_match),
|
||||
},
|
||||
.id_table = rmi_id,
|
||||
.probe_new = rmi_i2c_probe,
|
||||
.probe = rmi_i2c_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(rmi_i2c_driver);
|
||||
|
@ -418,7 +418,7 @@ static struct i2c_driver rmi_smb_driver = {
|
||||
.pm = pm_ptr(&rmi_smb_pm),
|
||||
},
|
||||
.id_table = rmi_id,
|
||||
.probe_new = rmi_smb_probe,
|
||||
.probe = rmi_smb_probe,
|
||||
.remove = rmi_smb_remove,
|
||||
};
|
||||
|
||||
|
@ -148,6 +148,7 @@ config HIL_MLC
|
||||
config SERIO_PCIPS2
|
||||
tristate "PCI PS/2 keyboard and PS/2 mouse controller"
|
||||
depends on PCI
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
Say Y here if you have a Mobility Docking station with PS/2
|
||||
keyboard and mice ports.
|
||||
|
@ -19,9 +19,26 @@
|
||||
|
||||
#define DRIVER_DESC "PS/2 driver library"
|
||||
|
||||
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
|
||||
MODULE_DESCRIPTION("PS/2 driver library");
|
||||
MODULE_LICENSE("GPL");
|
||||
#define PS2_CMD_SETSCALE11 0x00e6
|
||||
#define PS2_CMD_SETRES 0x10e8
|
||||
#define PS2_CMD_EX_SETLEDS 0x20eb
|
||||
#define PS2_CMD_SETLEDS 0x10ed
|
||||
#define PS2_CMD_GETID 0x02f2
|
||||
#define PS2_CMD_SETREP 0x10f3 /* Set repeat rate/set report rate */
|
||||
#define PS2_CMD_RESET_BAT 0x02ff
|
||||
|
||||
#define PS2_RET_BAT 0xaa
|
||||
#define PS2_RET_ID 0x00
|
||||
#define PS2_RET_ACK 0xfa
|
||||
#define PS2_RET_NAK 0xfe
|
||||
#define PS2_RET_ERR 0xfc
|
||||
|
||||
#define PS2_FLAG_ACK BIT(0) /* Waiting for ACK/NAK */
|
||||
#define PS2_FLAG_CMD BIT(1) /* Waiting for a command to finish */
|
||||
#define PS2_FLAG_CMD1 BIT(2) /* Waiting for the first byte of command response */
|
||||
#define PS2_FLAG_WAITID BIT(3) /* Command executing is GET ID */
|
||||
#define PS2_FLAG_NAK BIT(4) /* Last transmission was NAKed */
|
||||
#define PS2_FLAG_PASS_NOACK BIT(5) /* Pass non-ACK byte to receive handler */
|
||||
|
||||
static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
|
||||
unsigned int timeout, unsigned int max_attempts)
|
||||
@ -76,14 +93,17 @@ static int ps2_do_sendbyte(struct ps2dev *ps2dev, u8 byte,
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* ps2_sendbyte() sends a byte to the device and waits for acknowledge.
|
||||
* It doesn't handle retransmission, the caller is expected to handle
|
||||
/**
|
||||
* ps2_sendbyte - sends a byte to the device and wait for acknowledgement
|
||||
* @ps2dev: a PS/2 device to send the data to
|
||||
* @byte: data to be sent to the device
|
||||
* @timeout: timeout for sending the data and receiving an acknowledge
|
||||
*
|
||||
* The function doesn't handle retransmission, the caller is expected to handle
|
||||
* it when needed.
|
||||
*
|
||||
* ps2_sendbyte() can only be called from a process context.
|
||||
*/
|
||||
|
||||
int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
|
||||
{
|
||||
int retval;
|
||||
@ -99,6 +119,13 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_sendbyte);
|
||||
|
||||
/**
|
||||
* ps2_begin_command - mark beginning of execution of a complex command
|
||||
* @ps2dev: a PS/2 device executing the command
|
||||
*
|
||||
* Serializes a complex/compound command. Once command is finished
|
||||
* ps2_end_command() should be called.
|
||||
*/
|
||||
void ps2_begin_command(struct ps2dev *ps2dev)
|
||||
{
|
||||
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
|
||||
@ -107,6 +134,10 @@ void ps2_begin_command(struct ps2dev *ps2dev)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_begin_command);
|
||||
|
||||
/**
|
||||
* ps2_end_command - mark end of execution of a complex command
|
||||
* @ps2dev: a PS/2 device executing the command
|
||||
*/
|
||||
void ps2_end_command(struct ps2dev *ps2dev)
|
||||
{
|
||||
struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
|
||||
@ -115,11 +146,13 @@ void ps2_end_command(struct ps2dev *ps2dev)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_end_command);
|
||||
|
||||
/*
|
||||
* ps2_drain() waits for device to transmit requested number of bytes
|
||||
* and discards them.
|
||||
/**
|
||||
* ps2_drain - waits for device to transmit requested number of bytes
|
||||
* and discards them
|
||||
* @ps2dev: the PS/2 device that should be drained
|
||||
* @maxbytes: maximum number of bytes to be drained
|
||||
* @timeout: time to drain the device
|
||||
*/
|
||||
|
||||
void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
|
||||
{
|
||||
if (maxbytes > sizeof(ps2dev->cmdbuf)) {
|
||||
@ -142,11 +175,11 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_drain);
|
||||
|
||||
/*
|
||||
* ps2_is_keyboard_id() checks received ID byte against the list of
|
||||
* known keyboard IDs.
|
||||
/**
|
||||
* ps2_is_keyboard_id - checks received ID byte against the list of
|
||||
* known keyboard IDs
|
||||
* @id_byte: data byte that should be checked
|
||||
*/
|
||||
|
||||
bool ps2_is_keyboard_id(u8 id_byte)
|
||||
{
|
||||
static const u8 keyboard_ids[] = {
|
||||
@ -167,7 +200,6 @@ EXPORT_SYMBOL(ps2_is_keyboard_id);
|
||||
* response and tries to reduce remaining timeout to speed up command
|
||||
* completion.
|
||||
*/
|
||||
|
||||
static int ps2_adjust_timeout(struct ps2dev *ps2dev,
|
||||
unsigned int command, unsigned int timeout)
|
||||
{
|
||||
@ -217,13 +249,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev,
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* ps2_command() sends a command and its parameters to the mouse,
|
||||
* then waits for the response and puts it in the param array.
|
||||
/**
|
||||
* __ps2_command - send a command to PS/2 device
|
||||
* @ps2dev: the PS/2 device that should execute the command
|
||||
* @param: a buffer containing parameters to be sent along with the command,
|
||||
* or place where the results of the command execution will be deposited,
|
||||
* or both
|
||||
* @command: command word that encodes the command itself, as well as number of
|
||||
* additional parameter bytes that should be sent to the device and expected
|
||||
* length of the command response
|
||||
*
|
||||
* ps2_command() can only be called from a process context
|
||||
* Not serialized. Callers should use ps2_begin_command() and ps2_end_command()
|
||||
* to ensure proper serialization for complex commands.
|
||||
*/
|
||||
|
||||
int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
{
|
||||
unsigned int timeout;
|
||||
@ -247,17 +285,38 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
|
||||
serio_pause_rx(ps2dev->serio);
|
||||
|
||||
ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0;
|
||||
ps2dev->cmdcnt = receive;
|
||||
if (receive && param)
|
||||
for (i = 0; i < receive; i++)
|
||||
ps2dev->cmdbuf[(receive - 1) - i] = param[i];
|
||||
|
||||
/* Signal that we are sending the command byte */
|
||||
ps2dev->flags |= PS2_FLAG_ACK_CMD;
|
||||
switch (command) {
|
||||
case PS2_CMD_GETID:
|
||||
/*
|
||||
* Some mice do not ACK the "get ID" command, prepare to
|
||||
* handle this.
|
||||
*/
|
||||
ps2dev->flags = PS2_FLAG_WAITID;
|
||||
break;
|
||||
|
||||
case PS2_CMD_SETLEDS:
|
||||
case PS2_CMD_EX_SETLEDS:
|
||||
case PS2_CMD_SETREP:
|
||||
ps2dev->flags = PS2_FLAG_PASS_NOACK;
|
||||
break;
|
||||
|
||||
default:
|
||||
ps2dev->flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (receive) {
|
||||
/* Indicate that we expect response to the command. */
|
||||
ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
|
||||
if (param)
|
||||
for (i = 0; i < receive; i++)
|
||||
ps2dev->cmdbuf[(receive - 1) - i] = param[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Some devices (Synaptics) peform the reset before
|
||||
* Some devices (Synaptics) perform the reset before
|
||||
* ACKing the reset command, and so it can take a long
|
||||
* time before the ACK arrives.
|
||||
*/
|
||||
@ -267,9 +326,7 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
if (rc)
|
||||
goto out_reset_flags;
|
||||
|
||||
/* Now we are sending command parameters, if any */
|
||||
ps2dev->flags &= ~PS2_FLAG_ACK_CMD;
|
||||
|
||||
/* Send command parameters, if any. */
|
||||
for (i = 0; i < send; i++) {
|
||||
rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
|
||||
if (rc)
|
||||
@ -327,6 +384,20 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
}
|
||||
EXPORT_SYMBOL(__ps2_command);
|
||||
|
||||
/**
|
||||
* ps2_command - send a command to PS/2 device
|
||||
* @ps2dev: the PS/2 device that should execute the command
|
||||
* @param: a buffer containing parameters to be sent along with the command,
|
||||
* or place where the results of the command execution will be deposited,
|
||||
* or both
|
||||
* @command: command word that encodes the command itself, as well as number of
|
||||
* additional parameter bytes that should be sent to the device and expected
|
||||
* length of the command response
|
||||
*
|
||||
* Note: ps2_command() serializes the command execution so that only one
|
||||
* command can be executed at a time for either individual port or the entire
|
||||
* 8042 controller.
|
||||
*/
|
||||
int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
{
|
||||
int rc;
|
||||
@ -339,14 +410,16 @@ int ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_command);
|
||||
|
||||
/*
|
||||
* ps2_sliced_command() sends an extended PS/2 command to the mouse
|
||||
* using sliced syntax, understood by advanced devices, such as Logitech
|
||||
* or Synaptics touchpads. The command is encoded as:
|
||||
/**
|
||||
* ps2_sliced_command - sends an extended PS/2 command to a mouse
|
||||
* @ps2dev: the PS/2 device that should execute the command
|
||||
* @command: command byte
|
||||
*
|
||||
* The command is sent using "sliced" syntax understood by advanced devices,
|
||||
* such as Logitech or Synaptics touchpads. The command is encoded as:
|
||||
* 0xE6 0xE8 rr 0xE8 ss 0xE8 tt 0xE8 uu where (rr*64)+(ss*16)+(tt*4)+uu
|
||||
* is the command.
|
||||
*/
|
||||
|
||||
int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
|
||||
{
|
||||
int i;
|
||||
@ -372,25 +445,60 @@ int ps2_sliced_command(struct ps2dev *ps2dev, u8 command)
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_sliced_command);
|
||||
|
||||
/*
|
||||
* ps2_init() initializes ps2dev structure
|
||||
/**
|
||||
* ps2_init - initializes ps2dev structure
|
||||
* @ps2dev: structure to be initialized
|
||||
* @serio: serio port associated with the PS/2 device
|
||||
* @pre_receive_handler: validation handler to check basic communication state
|
||||
* @receive_handler: main protocol handler
|
||||
*
|
||||
* Prepares ps2dev structure for use in drivers for PS/2 devices.
|
||||
*/
|
||||
|
||||
void ps2_init(struct ps2dev *ps2dev, struct serio *serio)
|
||||
void ps2_init(struct ps2dev *ps2dev, struct serio *serio,
|
||||
ps2_pre_receive_handler_t pre_receive_handler,
|
||||
ps2_receive_handler_t receive_handler)
|
||||
{
|
||||
ps2dev->pre_receive_handler = pre_receive_handler;
|
||||
ps2dev->receive_handler = receive_handler;
|
||||
|
||||
mutex_init(&ps2dev->cmd_mutex);
|
||||
lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth);
|
||||
init_waitqueue_head(&ps2dev->wait);
|
||||
ps2dev->serio = serio;
|
||||
serio_set_drvdata(serio, ps2dev);
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_init);
|
||||
|
||||
/*
|
||||
* ps2_handle_ack() is supposed to be used in interrupt handler
|
||||
* to properly process ACK/NAK of a command from a PS/2 device.
|
||||
* ps2_handle_response() stores device's response to a command and notifies
|
||||
* the process waiting for completion of the command. Note that there is a
|
||||
* distinction between waiting for the first byte of the response, and
|
||||
* waiting for subsequent bytes. It is done so that callers could shorten
|
||||
* timeouts once first byte of response is received.
|
||||
*/
|
||||
static void ps2_handle_response(struct ps2dev *ps2dev, u8 data)
|
||||
{
|
||||
if (ps2dev->cmdcnt)
|
||||
ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
|
||||
|
||||
bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
|
||||
if (ps2dev->flags & PS2_FLAG_CMD1) {
|
||||
ps2dev->flags &= ~PS2_FLAG_CMD1;
|
||||
if (ps2dev->cmdcnt)
|
||||
wake_up(&ps2dev->wait);
|
||||
}
|
||||
|
||||
if (!ps2dev->cmdcnt) {
|
||||
ps2dev->flags &= ~PS2_FLAG_CMD;
|
||||
wake_up(&ps2dev->wait);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ps2_handle_ack() processes ACK/NAK of a command from a PS/2 device,
|
||||
* possibly applying workarounds for mice not acknowledging the "get ID"
|
||||
* command.
|
||||
*/
|
||||
static void ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
|
||||
{
|
||||
switch (data) {
|
||||
case PS2_RET_ACK:
|
||||
@ -427,68 +535,89 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
|
||||
* Do not signal errors if we get unexpected reply while
|
||||
* waiting for an ACK to the initial (first) command byte:
|
||||
* the device might not be quiesced yet and continue
|
||||
* delivering data.
|
||||
* delivering data. For certain commands (such as set leds and
|
||||
* set repeat rate) that can be used during normal device
|
||||
* operation, we even pass this data byte to the normal receive
|
||||
* handler.
|
||||
* Note that we reset PS2_FLAG_WAITID flag, so the workaround
|
||||
* for mice not acknowledging the Get ID command only triggers
|
||||
* on the 1st byte; if device spews data we really want to see
|
||||
* a real ACK from it.
|
||||
*/
|
||||
dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data);
|
||||
ps2dev->flags &= ~PS2_FLAG_WAITID;
|
||||
return ps2dev->flags & PS2_FLAG_ACK_CMD;
|
||||
if (ps2dev->flags & PS2_FLAG_PASS_NOACK)
|
||||
ps2dev->receive_handler(ps2dev, data);
|
||||
ps2dev->flags &= ~(PS2_FLAG_WAITID | PS2_FLAG_PASS_NOACK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ps2dev->nak) {
|
||||
if (!ps2dev->nak)
|
||||
ps2dev->flags &= ~PS2_FLAG_NAK;
|
||||
if (ps2dev->cmdcnt)
|
||||
ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
|
||||
}
|
||||
|
||||
ps2dev->flags &= ~PS2_FLAG_ACK;
|
||||
wake_up(&ps2dev->wait);
|
||||
|
||||
if (data != PS2_RET_ACK)
|
||||
if (!ps2dev->nak && data != PS2_RET_ACK)
|
||||
ps2_handle_response(ps2dev, data);
|
||||
|
||||
return true;
|
||||
else
|
||||
wake_up(&ps2dev->wait);
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_handle_ack);
|
||||
|
||||
/*
|
||||
* ps2_handle_response() is supposed to be used in interrupt handler
|
||||
* to properly store device's response to a command and notify process
|
||||
* waiting for completion of the command.
|
||||
* Clears state of PS/2 device after communication error by resetting majority
|
||||
* of flags and waking up waiters, if any.
|
||||
*/
|
||||
|
||||
bool ps2_handle_response(struct ps2dev *ps2dev, u8 data)
|
||||
static void ps2_cleanup(struct ps2dev *ps2dev)
|
||||
{
|
||||
if (ps2dev->cmdcnt)
|
||||
ps2dev->cmdbuf[--ps2dev->cmdcnt] = data;
|
||||
unsigned long old_flags = ps2dev->flags;
|
||||
|
||||
if (ps2dev->flags & PS2_FLAG_CMD1) {
|
||||
ps2dev->flags &= ~PS2_FLAG_CMD1;
|
||||
if (ps2dev->cmdcnt)
|
||||
wake_up(&ps2dev->wait);
|
||||
}
|
||||
/* reset all flags except last nak */
|
||||
ps2dev->flags &= PS2_FLAG_NAK;
|
||||
|
||||
if (!ps2dev->cmdcnt) {
|
||||
ps2dev->flags &= ~PS2_FLAG_CMD;
|
||||
wake_up(&ps2dev->wait);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_handle_response);
|
||||
|
||||
void ps2_cmd_aborted(struct ps2dev *ps2dev)
|
||||
{
|
||||
if (ps2dev->flags & PS2_FLAG_ACK)
|
||||
if (old_flags & PS2_FLAG_ACK)
|
||||
ps2dev->nak = 1;
|
||||
|
||||
if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
|
||||
if (old_flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
|
||||
wake_up(&ps2dev->wait);
|
||||
|
||||
/* reset all flags except last nack */
|
||||
ps2dev->flags &= PS2_FLAG_NAK;
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_cmd_aborted);
|
||||
|
||||
/**
|
||||
* ps2_interrupt - common interrupt handler for PS/2 devices
|
||||
* @serio: serio port for the device
|
||||
* @data: a data byte received from the device
|
||||
* @flags: flags such as %SERIO_PARITY or %SERIO_TIMEOUT indicating state of
|
||||
* the data transfer
|
||||
*
|
||||
* ps2_interrupt() invokes pre-receive handler, optionally handles command
|
||||
* acknowledgement and response from the device, and finally passes the data
|
||||
* to the main protocol handler for future processing.
|
||||
*/
|
||||
irqreturn_t ps2_interrupt(struct serio *serio, u8 data, unsigned int flags) {
|
||||
struct ps2dev *ps2dev = serio_get_drvdata(serio);
|
||||
enum ps2_disposition rc;
|
||||
|
||||
rc = ps2dev->pre_receive_handler(ps2dev, data, flags);
|
||||
switch (rc) {
|
||||
case PS2_ERROR:
|
||||
ps2_cleanup(ps2dev);
|
||||
break;
|
||||
|
||||
case PS2_IGNORE:
|
||||
break;
|
||||
|
||||
case PS2_PROCESS:
|
||||
if (ps2dev->flags & PS2_FLAG_ACK)
|
||||
ps2_handle_ack(ps2dev, data);
|
||||
else if (ps2dev->flags & PS2_FLAG_CMD)
|
||||
ps2_handle_response(ps2dev, data);
|
||||
else
|
||||
ps2dev->receive_handler(ps2dev, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
EXPORT_SYMBOL(ps2_interrupt);
|
||||
|
||||
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
|
||||
MODULE_DESCRIPTION("PS/2 driver library");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -43,8 +43,8 @@ static void input_test_exit(struct kunit *test)
|
||||
{
|
||||
struct input_dev *input_dev = test->priv;
|
||||
|
||||
input_unregister_device(input_dev);
|
||||
input_free_device(input_dev);
|
||||
if (input_dev)
|
||||
input_unregister_device(input_dev);
|
||||
}
|
||||
|
||||
static void input_test_poll(struct input_dev *input) { }
|
||||
@ -87,7 +87,7 @@ static void input_test_timestamp(struct kunit *test)
|
||||
static void input_test_match_device_id(struct kunit *test)
|
||||
{
|
||||
struct input_dev *input_dev = test->priv;
|
||||
struct input_device_id id;
|
||||
struct input_device_id id = { 0 };
|
||||
|
||||
/*
|
||||
* Must match when the input device bus, vendor, product, version
|
||||
@ -130,10 +130,42 @@ static void input_test_match_device_id(struct kunit *test)
|
||||
KUNIT_ASSERT_FALSE(test, input_match_device_id(input_dev, &id));
|
||||
}
|
||||
|
||||
static void input_test_grab(struct kunit *test)
|
||||
{
|
||||
struct input_dev *input_dev = test->priv;
|
||||
struct input_handle test_handle;
|
||||
struct input_handler handler;
|
||||
struct input_handle handle;
|
||||
struct input_device_id id;
|
||||
int res;
|
||||
|
||||
handler.name = "handler";
|
||||
handler.id_table = &id;
|
||||
|
||||
handle.dev = input_get_device(input_dev);
|
||||
handle.name = dev_name(&input_dev->dev);
|
||||
handle.handler = &handler;
|
||||
res = input_grab_device(&handle);
|
||||
KUNIT_ASSERT_TRUE(test, res == 0);
|
||||
|
||||
test_handle.dev = input_get_device(input_dev);
|
||||
test_handle.name = dev_name(&input_dev->dev);
|
||||
test_handle.handler = &handler;
|
||||
res = input_grab_device(&test_handle);
|
||||
KUNIT_ASSERT_EQ(test, res, -EBUSY);
|
||||
|
||||
input_release_device(&handle);
|
||||
input_put_device(input_dev);
|
||||
res = input_grab_device(&test_handle);
|
||||
KUNIT_ASSERT_TRUE(test, res == 0);
|
||||
input_put_device(input_dev);
|
||||
}
|
||||
|
||||
static struct kunit_case input_tests[] = {
|
||||
KUNIT_CASE(input_test_polling),
|
||||
KUNIT_CASE(input_test_timestamp),
|
||||
KUNIT_CASE(input_test_match_device_id),
|
||||
KUNIT_CASE(input_test_grab),
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
@ -700,6 +700,7 @@ config TOUCHSCREEN_INEXIO
|
||||
|
||||
config TOUCHSCREEN_MK712
|
||||
tristate "ICS MicroClock MK712 touchscreen"
|
||||
depends on ISA
|
||||
help
|
||||
Say Y here if you have the ICS MicroClock MK712 touchscreen
|
||||
controller chip in your system.
|
||||
|
@ -62,7 +62,7 @@ static struct i2c_driver ad7879_i2c_driver = {
|
||||
.pm = &ad7879_pm_ops,
|
||||
.of_match_table = of_match_ptr(ad7879_i2c_dt_ids),
|
||||
},
|
||||
.probe_new = ad7879_i2c_probe,
|
||||
.probe = ad7879_i2c_probe,
|
||||
.id_table = ad7879_id,
|
||||
};
|
||||
|
||||
|
@ -182,7 +182,7 @@ static struct i2c_driver ar1021_i2c_driver = {
|
||||
.of_match_table = ar1021_i2c_of_match,
|
||||
},
|
||||
|
||||
.probe_new = ar1021_i2c_probe,
|
||||
.probe = ar1021_i2c_probe,
|
||||
.id_table = ar1021_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ar1021_i2c_driver);
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define MXT_TOUCH_KEYARRAY_T15 15
|
||||
#define MXT_TOUCH_PROXIMITY_T23 23
|
||||
#define MXT_TOUCH_PROXKEY_T52 52
|
||||
#define MXT_TOUCH_PTC_KEYS_T97 97
|
||||
#define MXT_PROCI_GRIPFACE_T20 20
|
||||
#define MXT_PROCG_NOISE_T22 22
|
||||
#define MXT_PROCI_ONETOUCH_T24 24
|
||||
@ -326,9 +327,13 @@ struct mxt_data {
|
||||
u16 T71_address;
|
||||
u8 T9_reportid_min;
|
||||
u8 T9_reportid_max;
|
||||
u8 T15_reportid_min;
|
||||
u8 T15_reportid_max;
|
||||
u16 T18_address;
|
||||
u8 T19_reportid;
|
||||
u16 T44_address;
|
||||
u8 T97_reportid_min;
|
||||
u8 T97_reportid_max;
|
||||
u8 T100_reportid_min;
|
||||
u8 T100_reportid_max;
|
||||
|
||||
@ -344,6 +349,9 @@ struct mxt_data {
|
||||
u32 *t19_keymap;
|
||||
unsigned int t19_num_keys;
|
||||
|
||||
u32 *t15_keymap;
|
||||
unsigned int t15_num_keys;
|
||||
|
||||
enum mxt_suspend_mode suspend_mode;
|
||||
|
||||
u32 wakeup_method;
|
||||
@ -375,6 +383,7 @@ static bool mxt_object_readable(unsigned int type)
|
||||
case MXT_TOUCH_KEYARRAY_T15:
|
||||
case MXT_TOUCH_PROXIMITY_T23:
|
||||
case MXT_TOUCH_PROXKEY_T52:
|
||||
case MXT_TOUCH_PTC_KEYS_T97:
|
||||
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
||||
case MXT_PROCI_GRIPFACE_T20:
|
||||
case MXT_PROCG_NOISE_T22:
|
||||
@ -891,6 +900,24 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
|
||||
data->update_input = true;
|
||||
}
|
||||
|
||||
static void mxt_proc_t15_messages(struct mxt_data *data, u8 *message)
|
||||
{
|
||||
struct input_dev *input_dev = data->input_dev;
|
||||
unsigned long keystates = get_unaligned_le32(&message[2]);
|
||||
int key;
|
||||
|
||||
for (key = 0; key < data->t15_num_keys; key++)
|
||||
input_report_key(input_dev, data->t15_keymap[key],
|
||||
keystates & BIT(key));
|
||||
|
||||
data->update_input = true;
|
||||
}
|
||||
|
||||
static void mxt_proc_t97_messages(struct mxt_data *data, u8 *message)
|
||||
{
|
||||
mxt_proc_t15_messages(data, message);
|
||||
}
|
||||
|
||||
static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
|
||||
{
|
||||
struct device *dev = &data->client->dev;
|
||||
@ -1017,6 +1044,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
|
||||
} else if (report_id >= data->T9_reportid_min &&
|
||||
report_id <= data->T9_reportid_max) {
|
||||
mxt_proc_t9_message(data, message);
|
||||
} else if (report_id >= data->T15_reportid_min &&
|
||||
report_id <= data->T15_reportid_max) {
|
||||
mxt_proc_t15_messages(data, message);
|
||||
} else if (report_id >= data->T97_reportid_min &&
|
||||
report_id <= data->T97_reportid_max) {
|
||||
mxt_proc_t97_messages(data, message);
|
||||
} else if (report_id >= data->T100_reportid_min &&
|
||||
report_id <= data->T100_reportid_max) {
|
||||
mxt_proc_t100_message(data, message);
|
||||
@ -1689,9 +1722,13 @@ static void mxt_free_object_table(struct mxt_data *data)
|
||||
data->T71_address = 0;
|
||||
data->T9_reportid_min = 0;
|
||||
data->T9_reportid_max = 0;
|
||||
data->T15_reportid_min = 0;
|
||||
data->T15_reportid_max = 0;
|
||||
data->T18_address = 0;
|
||||
data->T19_reportid = 0;
|
||||
data->T44_address = 0;
|
||||
data->T97_reportid_min = 0;
|
||||
data->T97_reportid_max = 0;
|
||||
data->T100_reportid_min = 0;
|
||||
data->T100_reportid_max = 0;
|
||||
data->max_reportid = 0;
|
||||
@ -1764,6 +1801,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
|
||||
object->num_report_ids - 1;
|
||||
data->num_touchids = object->num_report_ids;
|
||||
break;
|
||||
case MXT_TOUCH_KEYARRAY_T15:
|
||||
data->T15_reportid_min = min_id;
|
||||
data->T15_reportid_max = max_id;
|
||||
break;
|
||||
case MXT_SPT_COMMSCONFIG_T18:
|
||||
data->T18_address = object->start_address;
|
||||
break;
|
||||
@ -1773,6 +1814,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
|
||||
case MXT_SPT_GPIOPWM_T19:
|
||||
data->T19_reportid = min_id;
|
||||
break;
|
||||
case MXT_TOUCH_PTC_KEYS_T97:
|
||||
data->T97_reportid_min = min_id;
|
||||
data->T97_reportid_max = max_id;
|
||||
break;
|
||||
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
||||
data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
|
||||
data->T100_reportid_min = min_id;
|
||||
@ -2050,6 +2095,7 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||
int error;
|
||||
unsigned int num_mt_slots;
|
||||
unsigned int mt_flags = 0;
|
||||
int i;
|
||||
|
||||
switch (data->multitouch) {
|
||||
case MXT_TOUCH_MULTI_T9:
|
||||
@ -2095,6 +2141,10 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||
input_dev->open = mxt_input_open;
|
||||
input_dev->close = mxt_input_close;
|
||||
|
||||
input_dev->keycode = data->t15_keymap;
|
||||
input_dev->keycodemax = data->t15_num_keys;
|
||||
input_dev->keycodesize = sizeof(data->t15_keymap[0]);
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||
|
||||
/* For single touch */
|
||||
@ -2162,6 +2212,13 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||
0, 255, 0, 0);
|
||||
}
|
||||
|
||||
/* For T15 and T97 Key Array */
|
||||
if (data->T15_reportid_min || data->T97_reportid_min) {
|
||||
for (i = 0; i < data->t15_num_keys; i++)
|
||||
input_set_capability(input_dev,
|
||||
EV_KEY, data->t15_keymap[i]);
|
||||
}
|
||||
|
||||
input_set_drvdata(input_dev, data);
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
@ -3080,8 +3137,10 @@ static void mxt_input_close(struct input_dev *dev)
|
||||
static int mxt_parse_device_properties(struct mxt_data *data)
|
||||
{
|
||||
static const char keymap_property[] = "linux,gpio-keymap";
|
||||
static const char buttons_property[] = "linux,keycodes";
|
||||
struct device *dev = &data->client->dev;
|
||||
u32 *keymap;
|
||||
u32 *buttonmap;
|
||||
int n_keys;
|
||||
int error;
|
||||
|
||||
@ -3111,6 +3170,32 @@ static int mxt_parse_device_properties(struct mxt_data *data)
|
||||
data->t19_num_keys = n_keys;
|
||||
}
|
||||
|
||||
if (device_property_present(dev, buttons_property)) {
|
||||
n_keys = device_property_count_u32(dev, buttons_property);
|
||||
if (n_keys <= 0) {
|
||||
error = n_keys < 0 ? n_keys : -EINVAL;
|
||||
dev_err(dev, "invalid/malformed '%s' property: %d\n",
|
||||
buttons_property, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
|
||||
GFP_KERNEL);
|
||||
if (!buttonmap)
|
||||
return -ENOMEM;
|
||||
|
||||
error = device_property_read_u32_array(dev, buttons_property,
|
||||
buttonmap, n_keys);
|
||||
if (error) {
|
||||
dev_err(dev, "failed to parse '%s' property: %d\n",
|
||||
buttons_property, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
data->t15_keymap = buttonmap;
|
||||
data->t15_num_keys = n_keys;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3377,7 +3462,7 @@ static struct i2c_driver mxt_driver = {
|
||||
.acpi_match_table = ACPI_PTR(mxt_acpi_id),
|
||||
.pm = pm_sleep_ptr(&mxt_pm_ops),
|
||||
},
|
||||
.probe_new = mxt_probe,
|
||||
.probe = mxt_probe,
|
||||
.remove = mxt_remove,
|
||||
.id_table = mxt_id,
|
||||
};
|
||||
|
@ -636,7 +636,7 @@ static struct i2c_driver auo_pixcir_driver = {
|
||||
.pm = pm_sleep_ptr(&auo_pixcir_pm_ops),
|
||||
.of_match_table = of_match_ptr(auo_pixcir_ts_dt_idtable),
|
||||
},
|
||||
.probe_new = auo_pixcir_probe,
|
||||
.probe = auo_pixcir_probe,
|
||||
.id_table = auo_pixcir_idtable,
|
||||
};
|
||||
|
||||
|
@ -617,7 +617,7 @@ static struct i2c_driver bu21013_driver = {
|
||||
.name = DRIVER_TP,
|
||||
.pm = pm_sleep_ptr(&bu21013_dev_pm_ops),
|
||||
},
|
||||
.probe_new = bu21013_probe,
|
||||
.probe = bu21013_probe,
|
||||
.remove = bu21013_remove,
|
||||
.id_table = bu21013_id,
|
||||
};
|
||||
|
@ -474,7 +474,7 @@ static struct i2c_driver bu21029_driver = {
|
||||
.pm = pm_sleep_ptr(&bu21029_pm_ops),
|
||||
},
|
||||
.id_table = bu21029_ids,
|
||||
.probe_new = bu21029_probe,
|
||||
.probe = bu21029_probe,
|
||||
};
|
||||
module_i2c_driver(bu21029_driver);
|
||||
|
||||
|
@ -264,7 +264,7 @@ static struct i2c_driver icn8318_driver = {
|
||||
.pm = pm_sleep_ptr(&icn8318_pm_ops),
|
||||
.of_match_table = icn8318_of_match,
|
||||
},
|
||||
.probe_new = icn8318_probe,
|
||||
.probe = icn8318_probe,
|
||||
.id_table = icn8318_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -498,7 +498,7 @@ static struct i2c_driver icn8505_driver = {
|
||||
.pm = pm_sleep_ptr(&icn8505_pm_ops),
|
||||
.acpi_match_table = icn8505_acpi_match,
|
||||
},
|
||||
.probe_new = icn8505_probe,
|
||||
.probe = icn8505_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(icn8505_driver);
|
||||
|
@ -344,7 +344,7 @@ static struct i2c_driver cy8ctma140_driver = {
|
||||
.of_match_table = cy8ctma140_of_match,
|
||||
},
|
||||
.id_table = cy8ctma140_idtable,
|
||||
.probe_new = cy8ctma140_probe,
|
||||
.probe = cy8ctma140_probe,
|
||||
};
|
||||
module_i2c_driver(cy8ctma140_driver);
|
||||
|
||||
|
@ -279,7 +279,7 @@ static struct i2c_driver cy8ctmg110_driver = {
|
||||
.pm = pm_sleep_ptr(&cy8ctmg110_pm),
|
||||
},
|
||||
.id_table = cy8ctmg110_idtable,
|
||||
.probe_new = cy8ctmg110_probe,
|
||||
.probe = cy8ctmg110_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(cy8ctmg110_driver);
|
||||
|
@ -1263,9 +1263,8 @@ static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd)
|
||||
* Ensure we wait until the watchdog timer
|
||||
* running on a different CPU finishes
|
||||
*/
|
||||
del_timer_sync(&cd->watchdog_timer);
|
||||
timer_shutdown_sync(&cd->watchdog_timer);
|
||||
cancel_work_sync(&cd->watchdog_work);
|
||||
del_timer_sync(&cd->watchdog_timer);
|
||||
}
|
||||
|
||||
static void cyttsp4_watchdog_timer(struct timer_list *t)
|
||||
|
@ -60,7 +60,7 @@ static struct i2c_driver cyttsp4_i2c_driver = {
|
||||
.name = CYTTSP4_I2C_NAME,
|
||||
.pm = pm_ptr(&cyttsp4_pm_ops),
|
||||
},
|
||||
.probe_new = cyttsp4_i2c_probe,
|
||||
.probe = cyttsp4_i2c_probe,
|
||||
.remove = cyttsp4_i2c_remove,
|
||||
.id_table = cyttsp4_i2c_id,
|
||||
};
|
||||
|
@ -43,6 +43,7 @@
|
||||
#define HID_DESC_REG 0x1
|
||||
#define HID_INPUT_REG 0x3
|
||||
#define HID_OUTPUT_REG 0x4
|
||||
#define HID_COMMAND_REG 0x5
|
||||
|
||||
#define REPORT_ID_TOUCH 0x1
|
||||
#define REPORT_ID_BTN 0x3
|
||||
@ -68,6 +69,7 @@
|
||||
#define HID_APP_OUTPUT_REPORT_ID 0x2F
|
||||
#define HID_BL_RESPONSE_REPORT_ID 0x30
|
||||
#define HID_BL_OUTPUT_REPORT_ID 0x40
|
||||
#define HID_RESPONSE_REPORT_ID 0xF0
|
||||
|
||||
#define HID_OUTPUT_RESPONSE_REPORT_OFFSET 2
|
||||
#define HID_OUTPUT_RESPONSE_CMD_OFFSET 4
|
||||
@ -78,9 +80,15 @@
|
||||
#define HID_SYSINFO_BTN_MASK GENMASK(7, 0)
|
||||
#define HID_SYSINFO_MAX_BTN 8
|
||||
|
||||
#define HID_CMD_SET_POWER 0x8
|
||||
|
||||
#define HID_POWER_ON 0x0
|
||||
#define HID_POWER_SLEEP 0x1
|
||||
|
||||
#define CY_HID_OUTPUT_TIMEOUT_MS 200
|
||||
#define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT_MS 3000
|
||||
#define CY_HID_GET_HID_DESCRIPTOR_TIMEOUT_MS 4000
|
||||
#define CY_HID_SET_POWER_TIMEOUT 500
|
||||
|
||||
/* maximum number of concurrent tracks */
|
||||
#define TOUCH_REPORT_SIZE 10
|
||||
@ -100,6 +108,14 @@
|
||||
#define TOUCH_REPORT_USAGE_PG_MIN 0xFF010063
|
||||
#define TOUCH_COL_USAGE_PG 0x000D0022
|
||||
|
||||
#define SET_CMD_LOW(byte, bits) \
|
||||
((byte) = (((byte) & 0xF0) | ((bits) & 0x0F)))
|
||||
#define SET_CMD_HIGH(byte, bits)\
|
||||
((byte) = (((byte) & 0x0F) | ((bits) & 0xF0)))
|
||||
#define SET_CMD_OPCODE(byte, opcode) SET_CMD_LOW(byte, opcode)
|
||||
#define SET_CMD_REPORT_TYPE(byte, type) SET_CMD_HIGH(byte, ((type) << 4))
|
||||
#define SET_CMD_REPORT_ID(byte, id) SET_CMD_LOW(byte, id)
|
||||
|
||||
/* System Information interface definitions */
|
||||
struct cyttsp5_sensing_conf_data_dev {
|
||||
u8 electrodes_x;
|
||||
@ -557,6 +573,40 @@ static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts)
|
||||
return cyttsp5_get_sysinfo_regs(ts);
|
||||
}
|
||||
|
||||
static int cyttsp5_power_control(struct cyttsp5 *ts, bool on)
|
||||
{
|
||||
u8 state = on ? HID_POWER_ON : HID_POWER_SLEEP;
|
||||
u8 cmd[2] = { 0 };
|
||||
int rc;
|
||||
|
||||
SET_CMD_REPORT_TYPE(cmd[0], 0);
|
||||
SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP);
|
||||
SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER);
|
||||
|
||||
rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd));
|
||||
if (rc) {
|
||||
dev_err(ts->dev, "Failed to write power command %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = wait_for_completion_interruptible_timeout(&ts->cmd_done,
|
||||
msecs_to_jiffies(CY_HID_SET_POWER_TIMEOUT));
|
||||
if (rc <= 0) {
|
||||
dev_err(ts->dev, "HID power cmd execution timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (ts->response_buf[2] != HID_RESPONSE_REPORT_ID ||
|
||||
(ts->response_buf[3] & 0x03) != state ||
|
||||
(ts->response_buf[4] & 0x0f) != HID_CMD_SET_POWER) {
|
||||
dev_err(ts->dev, "Validation of the %s response failed\n",
|
||||
on ? "wakeup" : "sleep");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts)
|
||||
{
|
||||
int rc;
|
||||
@ -601,12 +651,7 @@ static int cyttsp5_get_hid_descriptor(struct cyttsp5 *ts,
|
||||
struct cyttsp5_hid_desc *desc)
|
||||
{
|
||||
struct device *dev = ts->dev;
|
||||
__le16 hid_desc_register = cpu_to_le16(HID_DESC_REG);
|
||||
int rc;
|
||||
u8 cmd[2];
|
||||
|
||||
/* Set HID descriptor register */
|
||||
memcpy(cmd, &hid_desc_register, sizeof(hid_desc_register));
|
||||
|
||||
rc = cyttsp5_write(ts, HID_DESC_REG, NULL, 0);
|
||||
if (rc) {
|
||||
@ -675,6 +720,10 @@ static irqreturn_t cyttsp5_handle_irq(int irq, void *handle)
|
||||
case HID_BTN_REPORT_ID:
|
||||
cyttsp5_btn_attention(ts->dev);
|
||||
break;
|
||||
case HID_RESPONSE_REPORT_ID:
|
||||
memcpy(ts->response_buf, ts->input_buf, size);
|
||||
complete(&ts->cmd_done);
|
||||
break;
|
||||
default:
|
||||
/* It is not an input but a command response */
|
||||
memcpy(ts->response_buf, ts->input_buf, size);
|
||||
@ -886,12 +935,35 @@ static const struct i2c_device_id cyttsp5_i2c_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
|
||||
|
||||
static int __maybe_unused cyttsp5_suspend(struct device *dev)
|
||||
{
|
||||
struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
cyttsp5_power_control(ts, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused cyttsp5_resume(struct device *dev)
|
||||
{
|
||||
struct cyttsp5 *ts = dev_get_drvdata(dev);
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
cyttsp5_power_control(ts, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cyttsp5_pm, cyttsp5_suspend, cyttsp5_resume);
|
||||
|
||||
static struct i2c_driver cyttsp5_i2c_driver = {
|
||||
.driver = {
|
||||
.name = CYTTSP5_NAME,
|
||||
.of_match_table = cyttsp5_of_match,
|
||||
.pm = &cyttsp5_pm,
|
||||
},
|
||||
.probe_new = cyttsp5_i2c_probe,
|
||||
.probe = cyttsp5_i2c_probe,
|
||||
.id_table = cyttsp5_i2c_id,
|
||||
};
|
||||
module_i2c_driver(cyttsp5_i2c_driver);
|
||||
|
@ -66,7 +66,7 @@ static struct i2c_driver cyttsp_i2c_driver = {
|
||||
.pm = pm_sleep_ptr(&cyttsp_pm_ops),
|
||||
.of_match_table = cyttsp_of_i2c_match,
|
||||
},
|
||||
.probe_new = cyttsp_i2c_probe,
|
||||
.probe = cyttsp_i2c_probe,
|
||||
.id_table = cyttsp_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -1241,6 +1241,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
|
||||
if (tsdata->wake_gpio) {
|
||||
usleep_range(5000, 6000);
|
||||
gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
|
||||
usleep_range(5000, 6000);
|
||||
}
|
||||
|
||||
if (tsdata->reset_gpio) {
|
||||
@ -1510,7 +1511,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = {
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.id_table = edt_ft5x06_ts_id,
|
||||
.probe_new = edt_ft5x06_ts_probe,
|
||||
.probe = edt_ft5x06_ts_probe,
|
||||
.remove = edt_ft5x06_ts_remove,
|
||||
};
|
||||
|
||||
|
@ -291,7 +291,7 @@ static struct i2c_driver eeti_ts_driver = {
|
||||
.pm = pm_sleep_ptr(&eeti_ts_pm),
|
||||
.of_match_table = of_match_ptr(of_eeti_ts_match),
|
||||
},
|
||||
.probe_new = eeti_ts_probe,
|
||||
.probe = eeti_ts_probe,
|
||||
.id_table = eeti_ts_id,
|
||||
};
|
||||
|
||||
|
@ -264,7 +264,7 @@ static struct i2c_driver egalax_ts_driver = {
|
||||
.of_match_table = egalax_ts_dt_ids,
|
||||
},
|
||||
.id_table = egalax_ts_id,
|
||||
.probe_new = egalax_ts_probe,
|
||||
.probe = egalax_ts_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(egalax_ts_driver);
|
||||
|
@ -351,7 +351,7 @@ static struct i2c_driver ektf2127_driver = {
|
||||
.pm = pm_sleep_ptr(&ektf2127_pm_ops),
|
||||
.of_match_table = of_match_ptr(ektf2127_of_match),
|
||||
},
|
||||
.probe_new = ektf2127_probe,
|
||||
.probe = ektf2127_probe,
|
||||
.id_table = ektf2127_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ektf2127_driver);
|
||||
|
@ -1673,7 +1673,7 @@ MODULE_DEVICE_TABLE(of, elants_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver elants_i2c_driver = {
|
||||
.probe_new = elants_i2c_probe,
|
||||
.probe = elants_i2c_probe,
|
||||
.id_table = elants_i2c_id,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
|
@ -460,7 +460,7 @@ static struct i2c_driver exc3000_driver = {
|
||||
.of_match_table = of_match_ptr(exc3000_of_match),
|
||||
},
|
||||
.id_table = exc3000_id,
|
||||
.probe_new = exc3000_probe,
|
||||
.probe = exc3000_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(exc3000_driver);
|
||||
|
@ -1544,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, goodix_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver goodix_ts_driver = {
|
||||
.probe_new = goodix_ts_probe,
|
||||
.probe = goodix_ts_probe,
|
||||
.remove = goodix_ts_remove,
|
||||
.id_table = goodix_ts_id,
|
||||
.driver = {
|
||||
|
@ -1136,7 +1136,7 @@ static struct i2c_driver hideep_driver = {
|
||||
.pm = pm_sleep_ptr(&hideep_pm_ops),
|
||||
},
|
||||
.id_table = hideep_i2c_id,
|
||||
.probe_new = hideep_probe,
|
||||
.probe = hideep_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(hideep_driver);
|
||||
|
@ -349,7 +349,7 @@ MODULE_DEVICE_TABLE(of, himax_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver himax_ts_driver = {
|
||||
.probe_new = himax_probe,
|
||||
.probe = himax_probe,
|
||||
.id_table = himax_ts_id,
|
||||
.driver = {
|
||||
.name = "Himax-hx83112b-TS",
|
||||
|
@ -580,7 +580,7 @@ static struct i2c_driver hycon_hy46xx_driver = {
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.id_table = hycon_hy46xx_id,
|
||||
.probe_new = hycon_hy46xx_probe,
|
||||
.probe = hycon_hy46xx_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(hycon_hy46xx_driver);
|
||||
|
@ -488,7 +488,7 @@ static struct i2c_driver hynitron_i2c_driver = {
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
},
|
||||
.id_table = hyn_tpd_id,
|
||||
.probe_new = hyn_probe,
|
||||
.probe = hyn_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(hynitron_i2c_driver);
|
||||
|
@ -370,22 +370,33 @@ static int ili251x_firmware_update_resolution(struct device *dev)
|
||||
|
||||
/* The firmware update blob might have changed the resolution. */
|
||||
error = priv->chip->read_reg(client, REG_PANEL_INFO, &rs, sizeof(rs));
|
||||
if (error)
|
||||
return error;
|
||||
if (!error) {
|
||||
resx = le16_to_cpup((__le16 *)rs);
|
||||
resy = le16_to_cpup((__le16 *)(rs + 2));
|
||||
|
||||
resx = le16_to_cpup((__le16 *)rs);
|
||||
resy = le16_to_cpup((__le16 *)(rs + 2));
|
||||
/* The value reported by the firmware is invalid. */
|
||||
if (!resx || resx == 0xffff || !resy || resy == 0xffff)
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
/* The value reported by the firmware is invalid. */
|
||||
if (!resx || resx == 0xffff || !resy || resy == 0xffff)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* In case of error, the firmware might be stuck in bootloader mode,
|
||||
* e.g. after a failed firmware update. Set maximum resolution, but
|
||||
* do not fail to probe, so the user can re-trigger the firmware
|
||||
* update and recover the touch controller.
|
||||
*/
|
||||
if (error) {
|
||||
dev_warn(dev, "Invalid resolution reported by controller.\n");
|
||||
resx = 16384;
|
||||
resy = 16384;
|
||||
}
|
||||
|
||||
input_abs_set_max(priv->input, ABS_X, resx - 1);
|
||||
input_abs_set_max(priv->input, ABS_Y, resy - 1);
|
||||
input_abs_set_max(priv->input, ABS_MT_POSITION_X, resx - 1);
|
||||
input_abs_set_max(priv->input, ABS_MT_POSITION_Y, resy - 1);
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
static ssize_t ili251x_firmware_update_firmware_version(struct device *dev)
|
||||
@ -977,11 +988,10 @@ static int ili210x_i2c_probe(struct i2c_client *client)
|
||||
if (priv->chip->has_pressure_reg)
|
||||
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0);
|
||||
error = ili251x_firmware_update_cached_state(dev);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to cache firmware information, err: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
dev_warn(dev, "Unable to cache firmware information, err: %d\n",
|
||||
error);
|
||||
|
||||
touchscreen_parse_properties(input, true, &priv->prop);
|
||||
|
||||
error = input_mt_init_slots(input, priv->chip->max_touches,
|
||||
@ -1043,7 +1053,7 @@ static struct i2c_driver ili210x_ts_driver = {
|
||||
.of_match_table = ili210x_dt_ids,
|
||||
},
|
||||
.id_table = ili210x_i2c_id,
|
||||
.probe_new = ili210x_i2c_probe,
|
||||
.probe = ili210x_i2c_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(ili210x_ts_driver);
|
||||
|
@ -679,7 +679,7 @@ static struct i2c_driver ilitek_ts_i2c_driver = {
|
||||
.of_match_table = of_match_ptr(ilitek_ts_i2c_match),
|
||||
.acpi_match_table = ACPI_PTR(ilitekts_acpi_id),
|
||||
},
|
||||
.probe_new = ilitek_ts_i2c_probe,
|
||||
.probe = ilitek_ts_i2c_probe,
|
||||
.id_table = ilitek_ts_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ilitek_ts_i2c_driver);
|
||||
|
@ -357,7 +357,7 @@ static struct i2c_driver imagis_ts_driver = {
|
||||
.pm = pm_sleep_ptr(&imagis_pm_ops),
|
||||
.of_match_table = of_match_ptr(imagis_of_match),
|
||||
},
|
||||
.probe_new = imagis_probe,
|
||||
.probe = imagis_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(imagis_ts_driver);
|
||||
|
@ -1093,7 +1093,7 @@ static struct i2c_driver iqs5xx_i2c_driver = {
|
||||
.pm = pm_sleep_ptr(&iqs5xx_pm),
|
||||
},
|
||||
.id_table = iqs5xx_id,
|
||||
.probe_new = iqs5xx_probe,
|
||||
.probe = iqs5xx_probe,
|
||||
};
|
||||
module_i2c_driver(iqs5xx_i2c_driver);
|
||||
|
||||
|
@ -230,7 +230,7 @@ static struct i2c_driver max11801_ts_driver = {
|
||||
.of_match_table = max11801_ts_dt_ids,
|
||||
},
|
||||
.id_table = max11801_ts_id,
|
||||
.probe_new = max11801_ts_probe,
|
||||
.probe = max11801_ts_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(max11801_ts_driver);
|
||||
|
@ -272,7 +272,7 @@ static const struct i2c_device_id mcs5000_ts_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
|
||||
|
||||
static struct i2c_driver mcs5000_ts_driver = {
|
||||
.probe_new = mcs5000_ts_probe,
|
||||
.probe = mcs5000_ts_probe,
|
||||
.driver = {
|
||||
.name = "mcs5000_ts",
|
||||
.pm = pm_sleep_ptr(&mcs5000_ts_pm),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user