Commit 1f89a590 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:

 - a new driver for SparkFun Qwiic Joystick

 - pm8941-pwrkey driver now supports PMK8350

 - a bunch of assorted driver fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (44 commits)
  Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl
  Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
  Input: trackpoint - use kobj_to_dev()
  Input: atkbd - use kobj_to_dev()
  Input: tsc200x-core - use kobj_to_dev()
  Input: ims-pcu - use kobj_to_dev()
  Input: cros_ec_keyb - use kobj_to_dev() API
  dt-bindings: input: touchscreen: st1232: Convert to json-schema
  Input: i8042 - fix typos in comments
  Input: add SparkFun Qwiic Joystick driver
  dt-bindings: Add vendor prefix and bindings for Qwiic Joystick
  Input: cy8ctmg110_ts - switch to using gpiod API
  Input: cy8ctmg110_ts - switch to using managed resources
  Input: cy8ctmg110_ts - use endian helpers when converting data on wire
  Input: cy8ctmg110_ts - let I2C core configure wake interrupt
  Input: cy8ctmg110_ts - do not hardcode as wakeup source
  Input: cy8ctmg110_ts - do not hard code interrupt trigger
  Input: cy8ctmg110_ts - rely on platform code to supply interrupt
  Input: resistive-adc-touch - fix uninitialized variable 'press'
  Input: pm8941-pwrkey - add support for PMK8350 PON_HLOS PMIC peripheral
  ...
parents da85e7ed 818b2658
* Freescale MMA8450 3-Axis Accelerometer
Required properties:
- compatible : "fsl,mma8450".
- reg: the I2C address of MMA8450
Example:
accelerometer: mma8450@1c {
compatible = "fsl,mma8450";
reg = <0x1c>;
};
......@@ -8,6 +8,8 @@ PROPERTIES
Definition: must be one of:
"qcom,pm8941-pwrkey"
"qcom,pm8941-resin"
"qcom,pmk8350-pwrkey"
"qcom,pmk8350-resin"
- reg:
Usage: required
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/cypress,cy8ctma340.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cypress CY8CTMA340 series touchscreen controller bindings
description: The Cypress CY8CTMA340 series (also known as "CYTTSP" after
the marketing name Cypress TrueTouch Standard Product) touchscreens can
be connected to either I2C or SPI buses.
maintainers:
- Javier Martinez Canillas <javier@dowhile0.org>
- Linus Walleij <linus.walleij@linaro.org>
allOf:
- $ref: touchscreen.yaml#
properties:
$nodename:
pattern: "^touchscreen(@.*)?$"
compatible:
oneOf:
- const: cypress,cy8ctma340
- const: cypress,cy8ctst341
- const: cypress,cyttsp-spi
description: Legacy compatible for SPI connected CY8CTMA340
deprecated: true
- const: cypress,cyttsp-i2c
description: Legacy compatible for I2C connected CY8CTMA340
deprecated: true
reg:
description: I2C address when used on the I2C bus, or the SPI chip
select index when used on the SPI bus
clock-frequency:
description: I2C client clock frequency, defined for host when using
the device on the I2C bus
minimum: 0
maximum: 400000
spi-max-frequency:
description: SPI clock frequency, defined for host, defined when using
the device on the SPI bus. The throughput is maximum 2 Mbps so the
typical value is 2000000, if higher rates are used the total throughput
needs to be restricted to 2 Mbps.
minimum: 0
maximum: 6000000
interrupts:
description: Interrupt to host
maxItems: 1
vcpin-supply:
description: Analog power supply regulator on VCPIN pin
vdd-supply:
description: Digital power supply regulator on VDD pin
reset-gpios:
description: Reset line for the touchscreen, should be tagged
as GPIO_ACTIVE_LOW
bootloader-key:
description: the 8-byte bootloader key that is required to switch
the chip from bootloader mode (default mode) to application mode
$ref: /schemas/types.yaml#/definitions/uint8-array
minItems: 8
maxItems: 8
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-fuzz-x: true
touchscreen-fuzz-y: true
active-distance:
description: the distance in pixels beyond which a touch must move
before movement is detected and reported by the device
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 15
active-interval-ms:
description: the minimum period in ms between consecutive
scanning/processing cycles when the chip is in active mode
minimum: 0
maximum: 255
lowpower-interval-ms:
description: the minimum period in ms between consecutive
scanning/processing cycles when the chip is in low-power mode
minimum: 0
maximum: 2550
touch-timeout-ms:
description: minimum time in ms spent in the active power state while no
touches are detected before entering low-power mode
minimum: 0
maximum: 2550
use-handshake:
description: enable register-based handshake (boolean). This should only
be used if the chip is configured to use 'blocking communication with
timeout' (in this case the device generates an interrupt at the end of
every scanning/processing cycle)
$ref: /schemas/types.yaml#/definitions/flag
additionalProperties: false
required:
- compatible
- reg
- interrupts
- bootloader-key
- touchscreen-size-x
- touchscreen-size-y
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
num-cs = <1>;
cs-gpios = <&gpio 2 GPIO_ACTIVE_HIGH>;
touchscreen@0 {
compatible = "cypress,cy8ctma340";
reg = <0>;
interrupt-parent = <&gpio>;
interrupts = <20 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio 21 GPIO_ACTIVE_LOW>;
vdd-supply = <&ldo_aux1_reg>;
vcpin-supply = <&ldo_aux2_reg>;
bootloader-key = /bits/ 8 <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07>;
touchscreen-size-x = <480>;
touchscreen-size-y = <800>;
active-interval-ms = <0>;
touch-timeout-ms = <255>;
lowpower-interval-ms = <10>;
};
};
...
* Cypress cyttsp touchscreen controller
Required properties:
- compatible : must be "cypress,cyttsp-i2c" or "cypress,cyttsp-spi"
- reg : Device I2C address or SPI chip select number
- spi-max-frequency : Maximum SPI clocking speed of the device (for cyttsp-spi)
- interrupts : (gpio) interrupt to which the chip is connected
(see interrupt binding[0]).
- bootloader-key : the 8-byte bootloader key that is required to switch
the chip from bootloader mode (default mode) to
application mode.
This property has to be specified as an array of 8
'/bits/ 8' values.
Optional properties:
- reset-gpios : the reset gpio the chip is connected to
(see GPIO binding[1] for more details).
- touchscreen-size-x : horizontal resolution of touchscreen (in pixels)
- touchscreen-size-y : vertical resolution of touchscreen (in pixels)
- touchscreen-fuzz-x : horizontal noise value of the absolute input device
(in pixels)
- touchscreen-fuzz-y : vertical noise value of the absolute input device
(in pixels)
- active-distance : the distance in pixels beyond which a touch must move
before movement is detected and reported by the device.
Valid values: 0-15.
- active-interval-ms : the minimum period in ms between consecutive
scanning/processing cycles when the chip is in active mode.
Valid values: 0-255.
- lowpower-interval-ms : the minimum period in ms between consecutive
scanning/processing cycles when the chip is in low-power mode.
Valid values: 0-2550
- touch-timeout-ms : minimum time in ms spent in the active power state while no
touches are detected before entering low-power mode.
Valid values: 0-2550
- use-handshake : enable register-based handshake (boolean). This should
only be used if the chip is configured to use 'blocking
communication with timeout' (in this case the device
generates an interrupt at the end of every
scanning/processing cycle).
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[1]: Documentation/devicetree/bindings/gpio/gpio.txt
Example:
&i2c1 {
/* ... */
cyttsp@a {
compatible = "cypress,cyttsp-i2c";
reg = <0xa>;
interrupt-parent = <&gpio0>;
interrupts = <28 0>;
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <480>;
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>;
active-distance = <8>;
active-interval-ms = <0>;
lowpower-interval-ms = <200>;
touch-timeout-ms = <100>;
};
/* ... */
};
&mcspi1 {
/* ... */
cyttsp@0 {
compatible = "cypress,cyttsp-spi";
spi-max-frequency = <6000000>;
reg = <0>;
interrupt-parent = <&gpio0>;
interrupts = <28 0>;
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <800>;
touchscreen-size-y = <480>;
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>;
active-distance = <8>;
active-interval-ms = <0>;
lowpower-interval-ms = <200>;
touch-timeout-ms = <100>;
};
/* ... */
};
......@@ -56,6 +56,7 @@ properties:
wakeup-source: true
vcc-supply: true
iovcc-supply: true
gain:
description: Allows setting the sensitivity in the range from 0 to 31.
......
Generic resistive touchscreen ADC
Required properties:
- compatible: must be "resistive-adc-touch"
The device must be connected to an ADC device that provides channels for
position measurement and optional pressure.
Refer to
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
for details
- iio-channels: must have at least two channels connected to an ADC device.
These should correspond to the channels exposed by the ADC device and should
have the right index as the ADC device registers them. These channels
represent the relative position on the "x" and "y" axes.
- iio-channel-names: must have all the channels' names. Mandatory channels
are "x" and "y".
Optional properties:
- iio-channels: The third channel named "pressure" is optional and can be
used if the ADC device also measures pressure besides position.
If this channel is missing, pressure will be ignored and the touchscreen
will only report position.
- iio-channel-names: optional channel named "pressure".
Example:
resistive_touch: resistive_touch {
compatible = "resistive-adc-touch";
touchscreen-min-pressure = <50000>;
io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
io-channel-names = "x", "y", "pressure";
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/resistive-adc-touch.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic resistive touchscreen ADC
maintainers:
- Oleksij Rempel <o.rempel@pengutronix.de>
description: |
Generic ADC based resistive touchscreen controller
The device must be connected to an ADC device that provides channels for
position measurement and optional pressure.
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
const: resistive-adc-touch
io-channels:
minItems: 2
items:
- description: x
- description: y
- description: pressure (optional)
- description: z1 (optional)
- description: z2 (optional)
io-channel-names:
oneOf:
- items:
- enum: [x, y]
- enum: [x, y]
- items:
- enum: [x, y, pressure]
- enum: [x, y, pressure]
- enum: [x, y, pressure]
- items:
- enum: [x, y, z1, z2]
- enum: [x, y, z1, z2]
- enum: [x, y, z1, z2]
- enum: [x, y, z1, z2]
touchscreen-size-x: true
touchscreen-size-y: true
touchscreen-fuzz-x: true
touchscreen-fuzz-y: true
touchscreen-inverted-x: true
touchscreen-inverted-y: true
touchscreen-swapped-x-y: true
touchscreen-min-pressure: true
touchscreen-x-plate-ohms: true
additionalProperties: false
required:
- compatible
- io-channels
- io-channel-names
examples:
- |
touchscreen {
compatible = "resistive-adc-touch";
io-channels = <&adc 24>, <&adc 25>;
io-channel-names = "y", "x";
};
- |
touchscreen {
compatible = "resistive-adc-touch";
touchscreen-min-pressure = <50000>;
io-channels = <&adc 24>, <&adc 25>, <&adc 26>;
io-channel-names = "y", "pressure", "x";
};
- |
touchscreen {
compatible = "resistive-adc-touch";
touchscreen-min-pressure = <50000>;
io-channels = <&adc 1>, <&adc 2>, <&adc 3>, <&adc 4>;
io-channel-names = "x", "z1", "z2", "y";
touchscreen-x-plate-ohms = <800>;
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/touchscreen/sitronix,st1232.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sitronix st1232 or st1633 touchscreen controller
maintainers:
- Bastian Hecht <hechtb@gmail.com>
allOf:
- $ref: touchscreen.yaml#
properties:
compatible:
enum:
- sitronix,st1232
- sitronix,st1633
reg:
maxItems: 1
interrupts:
maxItems: 1
gpios:
description: A phandle to the reset GPIO
maxItems: 1
required:
- compatible
- reg
- interrupts
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@55 {
compatible = "sitronix,st1232";
reg = <0x55>;
interrupts = <2 0>;
gpios = <&gpio1 166 0>;
};
};
* Sitronix st1232 or st1633 touchscreen controller
Required properties:
- compatible: must contain one of
* "sitronix,st1232"
* "sitronix,st1633"
- reg: I2C address of the chip
- interrupts: interrupt to which the chip is connected
Optional properties:
- gpios: a phandle to the reset GPIO
For additional optional properties see: touchscreen.txt
Example:
i2c@00000000 {
/* ... */
touchscreen@55 {
compatible = "sitronix,st1232";
reg = <0x55>;
interrupts = <2 0>;
gpios = <&gpio1 166 0>;
};
/* ... */
};
......@@ -74,6 +74,12 @@ properties:
touchscreen-y-mm:
description: vertical length in mm of the touchscreen
touchscreen-x-plate-ohms:
description: Resistance of the X-plate in Ohms
touchscreen-y-plate-ohms:
description: Resistance of the Y-plate in Ohms
dependencies:
touchscreen-size-x: [ touchscreen-size-y ]
touchscreen-size-y: [ touchscreen-size-x ]
......
......@@ -272,6 +272,8 @@ properties:
# Socionext SynQuacer TPM MMIO module
- socionext,synquacer-tpm-mmio
# i2c serial eeprom (24cxx)
- sparkfun,qwiic-joystick
# SparkFun Qwiic Joystick (COM-15168) with i2c interface
- st,24c256
# Ambient Light Sensor with SMBUS/Two Wire Serial Interface
- taos,tsl2550
......
......@@ -1080,6 +1080,8 @@ patternProperties:
description: Sony Corporation
"^spansion,.*":
description: Spansion Inc.
"^sparkfun,.*":
description: SparkFun Electronics
"^sprd,.*":
description: Spreadtrum Communications Inc.
"^sst,.*":
......
......@@ -5051,11 +5051,10 @@ S: Maintained
F: drivers/input/touchscreen/cy8ctma140.c
CYTTSP TOUCHSCREEN DRIVER
M: Ferruh Yigit <fery@cypress.com>
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-input@vger.kernel.org
S: Supported
S: Maintained
F: drivers/input/touchscreen/cyttsp*
F: include/linux/input/cyttsp.h
D-LINK DIR-685 TOUCHKEYS DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
......
......@@ -7,9 +7,6 @@
* Input driver event debug module - dumps all events into syslog
*/
/*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h>
......
......@@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
memcpy(joydev->keypam, keypam, len);
for (i = 0; i < joydev->nkey; i++)
joydev->keymap[keypam[i] - BTN_MISC] = i;
joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
out:
kfree(keypam);
......
......@@ -372,6 +372,15 @@ config JOYSTICK_PXRC
To compile this driver as a module, choose M here: the
module will be called pxrc.
config JOYSTICK_QWIIC
tristate "SparkFun Qwiic Joystick"
depends on I2C
help
Say Y here if you want to use the SparkFun Qwiic Joystick.
To compile this driver as a module, choose M here: the
module will be called qwiic-joystick.
config JOYSTICK_FSIA6B
tristate "FlySky FS-iA6B RC Receiver"
select SERIO
......
......@@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 Oleh Kravchenko <oleg@kaa.org.ua>
*
* SparkFun Qwiic Joystick
* Product page:https://www.sparkfun.com/products/15168
* Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick
*/
#include <linux/bits.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#define DRV_NAME "qwiic-joystick"
#define QWIIC_JSK_REG_VERS 1
#define QWIIC_JSK_REG_DATA 3
#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0)
#define QWIIC_JSK_FUZZ 2
#define QWIIC_JSK_FLAT 2
#define QWIIC_JSK_POLL_INTERVAL 16
#define QWIIC_JSK_POLL_MIN 8
#define QWIIC_JSK_POLL_MAX 32
struct qwiic_jsk {
char phys[32];
struct input_dev *dev;
struct i2c_client *client;
};
struct qwiic_ver {
u8 major;
u8 minor;
};
struct qwiic_data {
__be16 x;
__be16 y;
u8 thumb;
};
static void qwiic_poll(struct input_dev *input)
{
struct qwiic_jsk *priv = input_get_drvdata(input);
struct qwiic_data data;
int err;
err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA,
sizeof(data), (u8 *)&data);
if (err != sizeof(data))
return;
input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6);
input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6);
input_report_key(input, BTN_THUMBL, !data.thumb);
input_sync(input);
}
static int qwiic_probe(struct i2c_client *client)
{
struct qwiic_jsk *priv;
struct qwiic_ver vers;
int err;
err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS,
sizeof(vers), (u8 *)&vers);
if (err < 0)
return err;
if (err != sizeof(vers))
return -EIO;
dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n",
vers.major, vers.minor);
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->client = client;
snprintf(priv->phys, sizeof(priv->phys),
"i2c/%s", dev_name(&client->dev));
i2c_set_clientdata(client, priv);
priv->dev = devm_input_allocate_device(&client->dev);
if (!priv->dev)
return -ENOMEM;
priv->dev->id.bustype = BUS_I2C;
priv->dev->name = "SparkFun Qwiic Joystick";
priv->dev->phys = priv->phys;
input_set_drvdata(priv->dev, priv);
input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS,
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS,
QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
input_set_capability(priv->dev, EV_KEY, BTN_THUMBL);
err = input_setup_polling(priv->dev, qwiic_poll);
if (err) {
dev_err(&client->dev, "failed to set up polling: %d\n", err);
return err;
}
input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL);
input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN);
input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX);
err = input_register_device(priv->dev);
if (err) {
dev_err(&client->dev, "failed to register joystick: %d\n", err);
return err;
}
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id of_qwiic_match[] = {
{ .compatible = "sparkfun,qwiic-joystick", },
{ },
};
MODULE_DEVICE_TABLE(of, of_qwiic_match);
#endif /* CONFIG_OF */
static const struct i2c_device_id qwiic_id_table[] = {
{ KBUILD_MODNAME, 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
static struct i2c_driver qwiic_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(of_qwiic_match),
},
.id_table = qwiic_id_table,
.probe_new = qwiic_probe,
};
module_i2c_driver(qwiic_driver);
MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver");
MODULE_LICENSE("GPL v2");
......@@ -79,6 +79,7 @@
#define MAP_DPAD_TO_BUTTONS (1 << 0)
#define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
#define MAP_STICKS_TO_NULL (1 << 2)
#define MAP_SELECT_BUTTON (1 << 3)
#define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \
MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL)
......@@ -130,6 +131,7 @@ static const struct xpad_device {
{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x045e, 0x0b12, "Microsoft Xbox One X pad", MAP_SELECT_BUTTON, XTYPE_XBOXONE },
{ 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
{ 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
......@@ -864,6 +866,8 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
/* menu/view buttons */
input_report_key(dev, BTN_START, data[4] & 0x04);
input_report_key(dev, BTN_SELECT, data[4] & 0x08);
if (xpad->mapping & MAP_SELECT_BUTTON)
input_report_key(dev, KEY_RECORD, data[22] & 0x01);
/* buttons A,B,X,Y */
input_report_key(dev, BTN_A, data[4] & 0x10);
......@@ -1674,6 +1678,8 @@ static int xpad_init_input(struct usb_xpad *xpad)
xpad->xtype == XTYPE_XBOXONE) {
for (i = 0; xpad360_btn[i] >= 0; i++)
input_set_capability(input_dev, EV_KEY, xpad360_btn[i]);
if (xpad->mapping & MAP_SELECT_BUTTON)
input_set_capability(input_dev, EV_KEY, KEY_RECORD);
} else {
for (i = 0; xpad_btn[i] >= 0; i++)
input_set_capability(input_dev, EV_KEY, xpad_btn[i]);
......
......@@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct atkbd *atkbd = serio_get_drvdata(serio);
......
......@@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
if (attr == &dev_attr_function_row_physmap.attr &&
......
......@@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
HIL_IDD_NUM_AXES_PER_SET(*idd)) {
printk(KERN_INFO PREFIX
"combo devices are not supported.\n");
error = -EINVAL;
goto bail1;
}
......
......@@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = {
static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct usb_interface *intf = to_usb_interface(dev);
struct ims_pcu *pcu = usb_get_intfdata(intf);
umode_t mode = attr->mode;
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
* Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2014, Sony Mobile Communications Inc.
*/
......@@ -22,6 +22,8 @@
#define PON_RT_STS 0x10
#define PON_KPDPWR_N_SET BIT(0)
#define PON_RESIN_N_SET BIT(1)
#define PON_GEN3_RESIN_N_SET BIT(6)
#define PON_GEN3_KPDPWR_N_SET BIT(7)
#define PON_PS_HOLD_RST_CTL 0x5a
#define PON_PS_HOLD_RST_CTL2 0x5b
......@@ -40,6 +42,10 @@
struct pm8941_data {
unsigned int pull_up_bit;
unsigned int status_bit;
bool supports_ps_hold_poff_config;
bool supports_debounce_config;
const char *name;
const char *phys;
};
struct pm8941_pwrkey {
......@@ -231,9 +237,10 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
pwrkey->input->name = "pm8941_pwrkey";
pwrkey->input->phys = "pm8941_pwrkey/input0";
pwrkey->input->name = pwrkey->data->name;
pwrkey->input->phys = pwrkey->data->phys;
if (pwrkey->data->supports_debounce_config) {
req_delay = (req_delay << 6) / USEC_PER_SEC;
req_delay = ilog2(req_delay);
......@@ -242,23 +249,28 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
PON_DBC_DELAY_MASK,
req_delay);
if (error) {
dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
dev_err(&pdev->dev, "failed to set debounce: %d\n",
error);
return error;
}
}
if (pwrkey->data->pull_up_bit) {
error = regmap_update_bits(pwrkey->regmap,
pwrkey->baseaddr + PON_PULL_CTL,
pwrkey->data->pull_up_bit,
pull_up ? pwrkey->data->pull_up_bit : 0);
pull_up ? pwrkey->data->pull_up_bit :
0);
if (error) {
dev_err(&pdev->dev, "failed to set pull: %d\n", error);
return error;
}
}
error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
NULL, pm8941_pwrkey_irq,
IRQF_ONESHOT,
"pm8941_pwrkey", pwrkey);
pwrkey->data->name, pwrkey);
if (error) {
dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
return error;
......@@ -271,6 +283,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return error;
}
if (pwrkey->data->supports_ps_hold_poff_config) {
pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
error = register_reboot_notifier(&pwrkey->reboot_notifier);
if (error) {
......@@ -278,6 +291,7 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
error);
return error;
}
}
platform_set_drvdata(pdev, pwrkey);
device_init_wakeup(&pdev->dev, 1);
......@@ -289,6 +303,7 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
if (pwrkey->data->supports_ps_hold_poff_config)
unregister_reboot_notifier(&pwrkey->reboot_notifier);
return 0;
......@@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
static const struct pm8941_data pwrkey_data = {
.pull_up_bit = PON_KPDPWR_PULL_UP,
.status_bit = PON_KPDPWR_N_SET,
.name = "pm8941_pwrkey",
.phys = "pm8941_pwrkey/input0",
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
};
static const struct pm8941_data resin_data = {
.pull_up_bit = PON_RESIN_PULL_UP,
.status_bit = PON_RESIN_N_SET,
.name = "pm8941_resin",
.phys = "pm8941_resin/input0",
.supports_ps_hold_poff_config = true,
.supports_debounce_config = true,
};
static const struct pm8941_data pon_gen3_pwrkey_data = {
.status_bit = PON_GEN3_KPDPWR_N_SET,
.name = "pmic_pwrkey",
.phys = "pmic_pwrkey/input0",
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
};
static const struct pm8941_data pon_gen3_resin_data = {
.status_bit = PON_GEN3_RESIN_N_SET,
.name = "pmic_resin",
.phys = "pmic_resin/input0",
.supports_ps_hold_poff_config = false,
.supports_debounce_config = false,
};
static const struct of_device_id pm8941_pwr_key_id_table[] = {
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
{ .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
{ .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
{ }
};
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
......
......@@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse,
static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct psmouse *psmouse = serio_get_drvdata(serio);
......
......@@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock);
/*
* Writers to AUX and KBD ports as well as users issuing i8042_command
* directly should acquire i8042_mutex (by means of calling
* i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that
* i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that
* they do not disturb each other (unfortunately in many i8042
* implementations write to one of the ports will immediately abort
* command that is being processed by another port).
......@@ -979,7 +979,7 @@ static int i8042_controller_selftest(void)
}
/*
* i8042_controller init initializes the i8042 controller, and,
* i8042_controller_init initializes the i8042 controller, and,
* most importantly, sets it into non-xlated mode if that's
* desired.
*/
......
......@@ -7,15 +7,14 @@
* Some cleanups by Alan Cox <alan@linux.intel.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/input/cy8ctmg110_pdata.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/byteorder.h>
#define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
......@@ -45,18 +44,18 @@ struct cy8ctmg110 {
struct input_dev *input;
char phys[32];
struct i2c_client *client;
int reset_pin;
int irq_pin;
struct gpio_desc *reset_gpio;
};
/*
* cy8ctmg110_power is the routine that is called when touch hardware
* will powered off or on.
* is being powered off or on. When powering on this routine de-asserts
* the RESET line, when powering off reset line is asserted.
*/
static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
{
if (ts->reset_pin)
gpio_direction_output(ts->reset_pin, 1 - poweron);
if (ts->reset_gpio)
gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
}
static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
......@@ -112,7 +111,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
{
struct input_dev *input = tsc->input;
unsigned char reg_p[CY8CTMG110_REG_MAX];
int x, y;
memset(reg_p, 0, CY8CTMG110_REG_MAX);
......@@ -120,16 +118,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
return -EIO;
y = reg_p[2] << 8 | reg_p[3];
x = reg_p[0] << 8 | reg_p[1];
/* Number of touch */
if (reg_p[8] == 0) {
input_report_key(input, BTN_TOUCH, 0);
} else {
input_report_key(input, BTN_TOUCH, 1);
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_X,
be16_to_cpup((__be16 *)(reg_p + 0)));
input_report_abs(input, ABS_Y,
be16_to_cpup((__be16 *)(reg_p + 2)));
}
input_sync(input);
......@@ -163,35 +160,35 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void cy8ctmg110_shut_off(void *_ts)
{
struct cy8ctmg110 *ts = _ts;
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
}
static int cy8ctmg110_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
struct cy8ctmg110 *ts;
struct input_dev *input_dev;
int err;
/* No pdata no way forward */
if (pdata == NULL) {
dev_err(&client->dev, "no pdata\n");
return -ENODEV;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA))
return -EIO;
ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
input_dev = input_allocate_device();
if (!ts || !input_dev) {
err = -ENOMEM;
goto err_free_mem;
}
ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev)
return -ENOMEM;
ts->client = client;
ts->input = input_dev;
ts->reset_pin = pdata->reset_pin;
ts->irq_pin = pdata->irq_pin;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
......@@ -199,84 +196,46 @@ static int cy8ctmg110_probe(struct i2c_client *client,
input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X,
CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
input_set_abs_params(input_dev, ABS_Y,
CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
if (ts->reset_pin) {
err = gpio_request(ts->reset_pin, NULL);
if (err) {
/* Request and assert reset line */
ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL,
GPIOD_OUT_HIGH);
if (IS_ERR(ts->reset_gpio)) {
err = PTR_ERR(ts->reset_gpio);
dev_err(&client->dev,
"Unable to request GPIO pin %d.\n",
ts->reset_pin);
goto err_free_mem;
}
"Unable to request reset GPIO: %d\n", err);
return err;
}
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
err = gpio_request(ts->irq_pin, "touch_irq_key");
if (err < 0) {
dev_err(&client->dev,
"Failed to request GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_shutoff_device;
}
err = gpio_direction_input(ts->irq_pin);
if (err < 0) {
dev_err(&client->dev,
"Failed to configure input direction for GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_free_irq_gpio;
}
client->irq = gpio_to_irq(ts->irq_pin);
if (client->irq < 0) {
err = client->irq;
dev_err(&client->dev,
"Unable to get irq number for GPIO %d, error %d\n",
ts->irq_pin, err);
goto err_free_irq_gpio;
}
err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts);
if (err)
return err;
err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"touch_reset_key", ts);
if (err < 0) {
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, cy8ctmg110_irq_thread,
IRQF_ONESHOT, "touch_reset_key", ts);
if (err) {
dev_err(&client->dev,
"irq %d busy? error %d\n", client->irq, err);
goto err_free_irq_gpio;
return err;
}
err = input_register_device(input_dev);
if (err)
goto err_free_irq;
return err;
i2c_set_clientdata(client, ts);
device_init_wakeup(&client->dev, 1);
return 0;
err_free_irq:
free_irq(client->irq, ts);
err_free_irq_gpio:
gpio_free(ts->irq_pin);
err_shutoff_device:
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
if (ts->reset_pin)
gpio_free(ts->reset_pin);
err_free_mem:
input_free_device(input_dev);
kfree(ts);
return err;
return 0;
}
static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
......@@ -284,12 +243,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
else {
if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
}
return 0;
}
......@@ -298,34 +256,16 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
else {
if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
}
return 0;
}
static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
static int cy8ctmg110_remove(struct i2c_client *client)
{
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
free_irq(client->irq, ts);
input_unregister_device(ts->input);
gpio_free(ts->irq_pin);
if (ts->reset_pin)
gpio_free(ts->reset_pin);
kfree(ts);
return 0;
}
static const struct i2c_device_id cy8ctmg110_idtable[] = {
{ CY8CTMG110_DRIVER_NAME, 1 },
{ }
......@@ -340,7 +280,6 @@ static struct i2c_driver cy8ctmg110_driver = {
},
.id_table = cy8ctmg110_idtable,
.probe = cy8ctmg110_probe,
.remove = cy8ctmg110_remove,
};
module_i2c_driver(cy8ctmg110_driver);
......
......@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include "cyttsp_core.h"
......@@ -45,8 +46,15 @@
#define CY_MAXZ 255
#define CY_DELAY_DFLT 20 /* ms */
#define CY_DELAY_MAX 500
#define CY_ACT_DIST_DFLT 0xF8
/* Active distance in pixels for a gesture to be reported */
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
#define CY_ACT_DIST_MASK 0x0F
/* Active Power state scanning/processing refresh interval */
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
/* Low Power state scanning/processing refresh interval */
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
/* touch timeout for the Active power */
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
#define CY_HNDSHK_BIT 0x80
/* device mode bits */
#define CY_OPERATE_MODE 0x00
......@@ -608,6 +616,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts)
return 0;
}
static void cyttsp_disable_regulators(void *_ts)
{
struct cyttsp *ts = _ts;
regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
ts->regulators);
}
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size)
{
......@@ -628,6 +644,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
ts->bus_ops = bus_ops;
ts->irq = irq;
/*
* VCPIN is the analog voltage supply
* VDD is the digital voltage supply
*/
ts->regulators[0].supply = "vcpin";
ts->regulators[1].supply = "vdd";
error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators),
ts->regulators);
if (error) {
dev_err(dev, "Failed to get regulators: %d\n", error);
return ERR_PTR(error);
}
error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
ts->regulators);
if (error) {
dev_err(dev, "Cannot enable regulators: %d\n", error);
return ERR_PTR(error);
}
error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts);
if (error) {
dev_err(dev, "failed to install chip disable handler\n");
return ERR_PTR(error);
}
ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ts->reset_gpio)) {
error = PTR_ERR(ts->reset_gpio);
......@@ -664,8 +706,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
}
error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_NO_AUTOEN,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"cyttsp", ts);
if (error) {
dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
......
......@@ -22,7 +22,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/input/cyttsp.h>
#include <linux/regulator/consumer.h>
#define CY_NUM_RETRY 16 /* max number of retries for read ops */
......@@ -122,6 +122,7 @@ struct cyttsp {
enum cyttsp_state state;
bool suspended;
struct regulator_bulk_data regulators[2];
struct gpio_desc *reset_gpio;
bool use_hndshk;
u8 act_dist;
......
......@@ -18,6 +18,8 @@
#include <linux/i2c.h>
#include <linux/input.h>
#define CY_I2C_NAME "cyttsp-i2c"
#define CY_I2C_DATA_SIZE 128
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
......@@ -52,10 +54,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
static const struct of_device_id cyttsp_of_i2c_match[] = {
{ .compatible = "cypress,cy8ctma340", },
{ .compatible = "cypress,cy8ctst341", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match);
static struct i2c_driver cyttsp_i2c_driver = {
.driver = {
.name = CY_I2C_NAME,
.pm = &cyttsp_pm_ops,
.of_match_table = cyttsp_of_i2c_match,
},
.probe = cyttsp_i2c_probe,
.id_table = cyttsp_i2c_id,
......
......@@ -20,6 +20,8 @@
#include <linux/input.h>
#include <linux/spi/spi.h>
#define CY_SPI_NAME "cyttsp-spi"
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_CMD_BYTES 4
......@@ -160,10 +162,18 @@ static int cyttsp_spi_probe(struct spi_device *spi)
return 0;
}
static const struct of_device_id cyttsp_of_spi_match[] = {
{ .compatible = "cypress,cy8ctma340", },
{ .compatible = "cypress,cy8ctst341", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match);
static struct spi_driver cyttsp_spi_driver = {
.driver = {
.name = CY_SPI_NAME,
.pm = &cyttsp_pm_ops,
.of_match_table = cyttsp_of_spi_match,
},
.probe = cyttsp_spi_probe,
};
......
......@@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data {
u16 num_x;
u16 num_y;
struct regulator *vcc;
struct regulator *iovcc;
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
......@@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
static void edt_ft5x06_disable_regulator(void *arg)
static void edt_ft5x06_disable_regulators(void *arg)
{
struct edt_ft5x06_ts_data *data = arg;
regulator_disable(data->vcc);
regulator_disable(data->iovcc);
}
static int edt_ft5x06_ts_probe(struct i2c_client *client,
......@@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return error;
}
tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc");
if (IS_ERR(tsdata->iovcc)) {
error = PTR_ERR(tsdata->iovcc);
if (error != -EPROBE_DEFER)
dev_err(&client->dev,
"failed to request iovcc regulator: %d\n", error);
return error;
}
error = regulator_enable(tsdata->iovcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable iovcc: %d\n", error);
return error;
}
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
usleep_range(10, 100);
error = regulator_enable(tsdata->vcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
regulator_disable(tsdata->iovcc);
return error;
}
error = devm_add_action_or_reset(&client->dev,
edt_ft5x06_disable_regulator,
edt_ft5x06_disable_regulators,
tsdata);
if (error)
return error;
......@@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
ret = regulator_disable(tsdata->vcc);
if (ret)
dev_warn(dev, "Failed to disable vcc\n");
ret = regulator_disable(tsdata->iovcc);
if (ret)
dev_warn(dev, "Failed to disable iovcc\n");
return 0;
}
......@@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
gpiod_set_value_cansleep(reset_gpio, 1);
usleep_range(5000, 6000);
ret = regulator_enable(tsdata->iovcc);
if (ret) {
dev_err(dev, "Failed to enable iovcc\n");
return ret;
}
/* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
usleep_range(10, 100);
ret = regulator_enable(tsdata->vcc);
if (ret) {
dev_err(dev, "Failed to enable vcc\n");
regulator_disable(tsdata->iovcc);
return ret;
}
......
......@@ -1369,8 +1369,7 @@ static bool elants_acpi_is_hid_device(struct device *dev)
}
#endif
static int elants_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int elants_i2c_probe(struct i2c_client *client)
{
union i2c_smbus_data dummy;
struct elants_data *ts;
......@@ -1396,7 +1395,7 @@ static int elants_i2c_probe(struct i2c_client *client,
init_completion(&ts->cmd_done);
ts->client = client;
ts->chip_id = (enum elants_chip_id)id->driver_data;
ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev);
i2c_set_clientdata(client, ts);
ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
......@@ -1636,15 +1635,15 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
#ifdef CONFIG_OF
static const struct of_device_id elants_of_match[] = {
{ .compatible = "elan,ekth3500" },
{ .compatible = "elan,ektf3624" },
{ .compatible = "elan,ekth3500", .data = (void *)EKTH3500 },
{ .compatible = "elan,ektf3624", .data = (void *)EKTF3624 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, elants_of_match);
#endif
static struct i2c_driver elants_i2c_driver = {
.probe = elants_i2c_probe,
.probe_new = elants_i2c_probe,
.id_table = elants_i2c_id,
.driver = {
.name = DEVICE_NAME,
......
......@@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts)
return -EIO;
}
static void hideep_nvm_unlock(struct hideep_ts *ts)
static int hideep_nvm_unlock(struct hideep_ts *ts)
{
u32 unmask_code;
int error;
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
if (error)
return error;
/* make it unprotected code */
unmask_code &= ~HIDEEP_PROT_MODE;
......@@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts)
NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
SET_FLASH_HWCONTROL();
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
return 0;
}
static int hideep_check_status(struct hideep_ts *ts)
......@@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts,
u32 addr = 0;
int error;
hideep_nvm_unlock(ts);
error = hideep_nvm_unlock(ts);
if (error)
return error;
while (ucode_len > 0) {
xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
......
......@@ -13,44 +13,78 @@
#include <linux/input/touchscreen.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#define DRIVER_NAME "resistive-adc-touch"
#define GRTS_DEFAULT_PRESSURE_MIN 50000
#define GRTS_DEFAULT_PRESSURE_MAX 65535
#define GRTS_MAX_POS_MASK GENMASK(11, 0)
#define GRTS_MAX_CHANNELS 4
enum grts_ch_type {
GRTS_CH_X,
GRTS_CH_Y,
GRTS_CH_PRESSURE,
GRTS_CH_Z1,
GRTS_CH_Z2,
GRTS_CH_MAX = GRTS_CH_Z2 + 1
};
/**
* struct grts_state - generic resistive touch screen information struct
* @x_plate_ohms: resistance of the X plate
* @pressure_min: number representing the minimum for the pressure
* @pressure: are we getting pressure info or not
* @iio_chans: list of channels acquired
* @iio_cb: iio_callback buffer for the data
* @input: the input device structure that we register
* @prop: touchscreen properties struct
* @ch_map: map of channels that are defined for the touchscreen
*/
struct grts_state {
u32 x_plate_ohms;
u32 pressure_min;
bool pressure;
struct iio_channel *iio_chans;
struct iio_cb_buffer *iio_cb;
struct input_dev *input;
struct touchscreen_properties prop;
u8 ch_map[GRTS_CH_MAX];
};
static int grts_cb(const void *data, void *private)
{
const u16 *touch_info = data;
struct grts_state *st = private;
unsigned int x, y, press = 0x0;
/* channel data coming in buffer in the order below */
x = touch_info[0];
y = touch_info[1];
if (st->pressure)
press = touch_info[2];
unsigned int x, y, press = 0;
x = touch_info[st->ch_map[GRTS_CH_X]];
y = touch_info[st->ch_map[GRTS_CH_Y]];
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
} else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
unsigned int Rt;
Rt = z2;
Rt -= z1;
Rt *= st->x_plate_ohms;
Rt = DIV_ROUND_CLOSEST(Rt, 16);
Rt *= x;
Rt /= z1;
Rt = DIV_ROUND_CLOSEST(Rt, 256);
/*
* On increased pressure the resistance (Rt) is decreasing
* so, convert values to make it looks as real pressure.
*/
if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
}
if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
/* report end of touch */
......@@ -94,12 +128,77 @@ static void grts_disable(void *data)
iio_channel_release_all_cb(data);
}
static int grts_map_channel(struct grts_state *st, struct device *dev,
enum grts_ch_type type, const char *name,
bool optional)
{
int idx;
idx = device_property_match_string(dev, "io-channel-names", name);
if (idx < 0) {
if (!optional)
return idx;
idx = GRTS_MAX_CHANNELS;
} else if (idx >= GRTS_MAX_CHANNELS) {
return -EOVERFLOW;
}
st->ch_map[type] = idx;
return 0;
}
static int grts_get_properties(struct grts_state *st, struct device *dev)
{
int error;
error = grts_map_channel(st, dev, GRTS_CH_X, "x", false);
if (error)
return error;
error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false);
if (error)
return error;
/* pressure is optional */
error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true);
if (error)
return error;
if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
st->pressure = true;
return 0;
}
/* if no pressure is defined, try optional z1 + z2 */
error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true);
if (error)
return error;
if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS)
return 0;
/* if z1 is provided z2 is not optional */
error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true);
if (error)
return error;
error = device_property_read_u32(dev,
"touchscreen-x-plate-ohms",
&st->x_plate_ohms);
if (error) {
dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
return error;
}
st->pressure = true;
return 0;
}
static int grts_probe(struct platform_device *pdev)
{
struct grts_state *st;
struct input_dev *input;
struct device *dev = &pdev->dev;
struct iio_channel *chan;
int error;
st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
......@@ -115,12 +214,13 @@ static int grts_probe(struct platform_device *pdev)
return error;
}
chan = &st->iio_chans[0];
st->pressure = false;
while (chan && chan->indio_dev) {
if (!strcmp(chan->channel->datasheet_name, "pressure"))
st->pressure = true;
chan++;
if (!device_property_present(dev, "io-channel-names"))
return -ENODEV;
error = grts_get_properties(st, dev);
if (error) {
dev_err(dev, "Failed to parse properties\n");
return error;
}
if (st->pressure) {
......@@ -148,7 +248,7 @@ static int grts_probe(struct platform_device *pdev)
input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
if (st->pressure)
input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
0xffff, 0, 0);
GRTS_DEFAULT_PRESSURE_MAX, 0, 0);
input_set_capability(input, EV_KEY, BTN_TOUCH);
......@@ -193,7 +293,7 @@ static struct platform_driver grts_driver = {
.probe = grts_probe,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(grts_of_match),
.of_match_table = grts_of_match,
},
};
......
......@@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = {
static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct tsc200x *ts = dev_get_drvdata(dev);
umode_t mode = attr->mode;
......
......@@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch)
int ret;
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0x01, 0x02, 0x0000, 0x0081,
NULL, 0, USB_CTRL_SET_TIMEOUT);
......@@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
if (ret)
return ret;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
MTOUCHUSB_RESET,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
......@@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
msleep(150);
for (i = 0; i < 3; i++) {
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
......@@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
}
/* start sending data */
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
TSC10_CMD_DATA1,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
......
......@@ -5,7 +5,6 @@
struct cy8ctmg110_pdata
{
int reset_pin; /* Reset pin is wired to this GPIO (optional) */
int irq_pin; /* IRQ pin is wired to this GPIO */
};
#endif
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Header file for:
* Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
* For use with Cypress Txx3xx parts.
* Supported parts include:
* CY8CTST341
* CY8CTMA340
*
* Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
* Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
*
* Contact Cypress Semiconductor at www.cypress.com (kev@cypress.com)
*/
#ifndef _CYTTSP_H_
#define _CYTTSP_H_
#define CY_SPI_NAME "cyttsp-spi"
#define CY_I2C_NAME "cyttsp-i2c"
/* Active Power state scanning/processing refresh interval */
#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
/* touch timeout for the Active power */
#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
/* Low Power state scanning/processing refresh interval */
#define CY_LP_INTRVL_DFLT 0x0A /* ms */
/* Active distance in pixels for a gesture to be reported */
#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
#endif /* _CYTTSP_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment