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

Pull input updates from Dmitry Torokhov:
 "A few new drivers:

   - driver for Azoteq IQS550/572/525 touch controllers

   - driver for Microchip AT42QT1050 keys

   - driver for GPIO controllable vibrators

   - support for GT5663 in Goodix driver

  ... along with miscellaneous driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: libps2 - mark expected switch fall-through
  Input: qt1050 - add Microchip AT42QT1050 support
  Input: add support for Azoteq IQS550/572/525
  Input: add a driver for GPIO controllable vibrators
  Input: synaptics-rmi4 - fix enum_fmt
  Input: synaptics-rmi4 - fill initial format
  HID: input: add mapping for KEY_KBD_LAYOUT_NEXT
  Input: add KEY_KBD_LAYOUT_NEXT
  Input: hyperv-keyboard - add module description
  Input: olpc_apsp - depend on ARCH_MMP
  Input: sun4i-a10-lradc-keys - add support for A83T
  Input: snvs_pwrkey - use dev_pm_set_wake_irq() to simplify code
  Input: lpc32xx-key - add clocks property and fix DT binding example
  Input: i8042 - signal wakeup from atkbd/psmouse
  Input: goodix - add GT5663 CTP support
  Input: goodix - add regulators suppot
  Input: evdev - use struct_size() in kzalloc() and vzalloc()
  Input: edt-ft5x06 - convert to use SPDX identifier
  Input: edt-ft5x06 - enable ACPI enumeration
This commit is contained in:
Linus Torvalds 2019-05-13 15:21:48 -07:00
commit 0aed4b2818
30 changed files with 2297 additions and 74 deletions

View File

@ -0,0 +1,37 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/bindings/input/gpio-vibrator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GPIO vibrator
maintainers:
- Luca Weiss <luca@z3ntu.xyz>
description: |+
Registers a GPIO device as vibrator, where the on/off capability is controlled by a GPIO.
properties:
compatible:
const: gpio-vibrator
enable-gpios:
maxItems: 1
vcc-supply:
description: Regulator that provides power
required:
- compatible
- enable-gpios
examples:
- |
#include <dt-bindings/gpio/gpio.h>
vibrator {
compatible = "gpio-vibrator";
enable-gpios = <&msmgpio 86 GPIO_ACTIVE_HIGH>;
vcc-supply = <&pm8941_l18>;
};

View File

@ -8,6 +8,7 @@ Required Properties:
- reg: Physical base address of the controller and length of memory mapped - reg: Physical base address of the controller and length of memory mapped
region. region.
- interrupts: The interrupt number to the cpu. - interrupts: The interrupt number to the cpu.
- clocks: phandle to clock controller plus clock-specifier pair
- nxp,debounce-delay-ms: Debounce delay in ms - nxp,debounce-delay-ms: Debounce delay in ms
- nxp,scan-delay-ms: Repeated scan period in ms - nxp,scan-delay-ms: Repeated scan period in ms
- linux,keymap: the key-code to be reported when the key is pressed - linux,keymap: the key-code to be reported when the key is pressed
@ -22,7 +23,9 @@ Example:
key@40050000 { key@40050000 {
compatible = "nxp,lpc3220-key"; compatible = "nxp,lpc3220-key";
reg = <0x40050000 0x1000>; reg = <0x40050000 0x1000>;
interrupts = <54 0>; clocks = <&clk LPC32XX_CLK_KEY>;
interrupt-parent = <&sic1>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
keypad,num-rows = <1>; keypad,num-rows = <1>;
keypad,num-columns = <1>; keypad,num-columns = <1>;
nxp,debounce-delay-ms = <3>; nxp,debounce-delay-ms = <3>;

View File

@ -0,0 +1,78 @@
Microchip AT42QT1050 Five-channel Touch Sensor IC
The AT42QT1050 (QT1050) is a QTouchADC sensor device. The device can sense from
one to five keys, dependent on mode. The QT1050 includes all signal processing
functions necessary to provide stable sensing under a wide variety of changing
conditions, and the outputs are fully debounced.
The touchkey device node should be placed inside an I2C bus node.
Required properties:
- compatible: Must be "microchip,qt1050"
- reg: The I2C address of the device
- interrupts: The sink for the touchpad's IRQ output,
see ../interrupt-controller/interrupts.txt
Optional properties:
- wakeup-source: touch keys can be used as a wakeup source
Each button (key) is represented as a sub-node:
Each not specified key or key with linux,code set to KEY_RESERVED gets disabled
in HW.
Subnode properties:
- linux,code: Keycode to emit.
- reg: The key number. Valid values: 0, 1, 2, 3, 4.
Optional subnode-properties:
If a optional property is missing or has a invalid value the default value is
taken.
- microchip,pre-charge-time-ns:
Each touchpad need some time to precharge. The value depends on the mechanical
layout.
Valid value range: 0 - 637500; values must be a multiple of 2500;
default is 0.
- microchip,average-samples:
Number of data samples which are averaged for each read.
Valid values: 1, 4, 16, 64, 256, 1024, 4096, 16384; default is 1.
- microchip,average-scaling:
The scaling factor which is used to scale the average-samples.
Valid values: 1, 2, 4, 8, 16, 32, 64, 128; default is 1.
- microchip,threshold:
Number of counts to register a touch detection.
Valid value range: 0 - 255; default is 20.
Example:
QT1050 with 3 non continuous keys, key2 and key4 are disabled.
touchkeys@41 {
compatible = "microchip,qt1050";
reg = <0x41>;
interrupt-parent = <&gpio0>;
interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
up@0 {
reg = <0>;
linux,code = <KEY_UP>;
microchip,average-samples = <64>;
microchip,average-scaling = <16>;
microchip,pre-charge-time-ns = <10000>;
};
right@1 {
reg = <1>;
linux,code = <KEY_RIGHT>;
microchip,average-samples = <64>;
microchip,average-scaling = <8>;
};
down@3 {
reg = <3>;
linux,code = <KEY_DOWN>;
microchip,average-samples = <256>;
microchip,average-scaling = <16>;
};
};

View File

@ -2,12 +2,14 @@ Allwinner sun4i low res adc attached tablet keys
------------------------------------------------ ------------------------------------------------
Required properties: Required properties:
- compatible: "allwinner,sun4i-a10-lradc-keys" - compatible: should be one of the following string:
"allwinner,sun4i-a10-lradc-keys"
"allwinner,sun8i-a83t-r-lradc"
- reg: mmio address range of the chip - reg: mmio address range of the chip
- interrupts: interrupt to which the chip is connected - interrupts: interrupt to which the chip is connected
- vref-supply: powersupply for the lradc reference voltage - vref-supply: powersupply for the lradc reference voltage
Each key is represented as a sub-node of "allwinner,sun4i-a10-lradc-keys": Each key is represented as a sub-node of the compatible mentioned above:
Required subnode-properties: Required subnode-properties:
- label: Descriptive name of the key. - label: Descriptive name of the key.

View File

@ -3,6 +3,7 @@ Device tree bindings for Goodix GT9xx series touchscreen controller
Required properties: Required properties:
- compatible : Should be "goodix,gt1151" - compatible : Should be "goodix,gt1151"
or "goodix,gt5663"
or "goodix,gt5688" or "goodix,gt5688"
or "goodix,gt911" or "goodix,gt911"
or "goodix,gt9110" or "goodix,gt9110"
@ -19,6 +20,8 @@ Optional properties:
- irq-gpios : GPIO pin used for IRQ. The driver uses the - irq-gpios : GPIO pin used for IRQ. The driver uses the
interrupt gpio pin as output to reset the device. interrupt gpio pin as output to reset the device.
- reset-gpios : GPIO pin used for reset - reset-gpios : GPIO pin used for reset
- AVDD28-supply : Analog power supply regulator on AVDD28 pin
- VDDIO-supply : GPIO power supply regulator on VDDIO pin
- touchscreen-inverted-x - touchscreen-inverted-x
- touchscreen-inverted-y - touchscreen-inverted-y
- touchscreen-size-x - touchscreen-size-x

View File

@ -0,0 +1,80 @@
Azoteq IQS550/572/525 Trackpad/Touchscreen Controller
Required properties:
- compatible : Must be equal to one of the following:
"azoteq,iqs550"
"azoteq,iqs572"
"azoteq,iqs525"
- reg : I2C slave address for the device.
- interrupts : GPIO to which the device's active-high RDY
output is connected (see [0]).
- reset-gpios : GPIO to which the device's active-low NRST
input is connected (see [1]).
Optional properties:
- touchscreen-min-x : See [2].
- touchscreen-min-y : See [2].
- touchscreen-size-x : See [2]. If this property is omitted, the
maximum x-coordinate is specified by the
device's "X Resolution" register.
- touchscreen-size-y : See [2]. If this property is omitted, the
maximum y-coordinate is specified by the
device's "Y Resolution" register.
- touchscreen-max-pressure : See [2]. Pressure is expressed as the sum of
the deltas across all channels impacted by a
touch event. A channel's delta is calculated
as its count value minus a reference, where
the count value is inversely proportional to
the channel's capacitance.
- touchscreen-fuzz-x : See [2].
- touchscreen-fuzz-y : See [2].
- touchscreen-fuzz-pressure : See [2].
- touchscreen-inverted-x : See [2]. Inversion is applied relative to that
which may already be specified by the device's
FLIP_X and FLIP_Y register fields.
- touchscreen-inverted-y : See [2]. Inversion is applied relative to that
which may already be specified by the device's
FLIP_X and FLIP_Y register fields.
- touchscreen-swapped-x-y : See [2]. Swapping is applied relative to that
which may already be specified by the device's
SWITCH_XY_AXIS register field.
[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
[1]: Documentation/devicetree/bindings/gpio/gpio.txt
[2]: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
Example:
&i2c1 {
/* ... */
touchscreen@74 {
compatible = "azoteq,iqs550";
reg = <0x74>;
interrupt-parent = <&gpio>;
interrupts = <17 4>;
reset-gpios = <&gpio 27 1>;
touchscreen-size-x = <640>;
touchscreen-size-y = <480>;
touchscreen-max-pressure = <16000>;
};
/* ... */
};

View File

@ -55,6 +55,7 @@ avic Shanghai AVIC Optoelectronics Co., Ltd.
avnet Avnet, Inc. avnet Avnet, Inc.
axentia Axentia Technologies AB axentia Axentia Technologies AB
axis Axis Communications AB axis Axis Communications AB
azoteq Azoteq (Pty) Ltd
bananapi BIPAI KEJI LIMITED bananapi BIPAI KEJI LIMITED
bhf Beckhoff Automation GmbH & Co. KG bhf Beckhoff Automation GmbH & Co. KG
bitmain Bitmain Technologies bitmain Bitmain Technologies

View File

@ -1051,6 +1051,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
case 0x28c: map_key_clear(KEY_SEND); break; case 0x28c: map_key_clear(KEY_SEND); break;
case 0x29d: map_key_clear(KEY_KBD_LAYOUT_NEXT); break;
case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV); break; case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV); break;
case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT); break; case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT); break;
case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP); break; case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP); break;

View File

@ -503,14 +503,13 @@ static int evdev_open(struct inode *inode, struct file *file)
{ {
struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
unsigned int size = sizeof(struct evdev_client) +
bufsize * sizeof(struct input_event);
struct evdev_client *client; struct evdev_client *client;
int error; int error;
client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); client = kzalloc(struct_size(client, buffer, bufsize),
GFP_KERNEL | __GFP_NOWARN);
if (!client) if (!client)
client = vzalloc(size); client = vzalloc(struct_size(client, buffer, bufsize));
if (!client) if (!client)
return -ENOMEM; return -ENOMEM;

View File

@ -137,6 +137,17 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
right-hand column will be interpreted as the key shown in the right-hand column will be interpreted as the key shown in the
left-hand column. left-hand column.
config KEYBOARD_QT1050
tristate "Microchip AT42QT1050 Touch Sensor Chip"
depends on I2C
select REGMAP_I2C
help
Say Y here if you want to use Microchip AT42QT1050 QTouch
Sensor chip as input device.
To compile this driver as a module, choose M here:
the module will be called qt1050
config KEYBOARD_QT1070 config KEYBOARD_QT1070
tristate "Atmel AT42QT1070 Touch Sensor Chip" tristate "Atmel AT42QT1070 Touch Sensor Chip"
depends on I2C depends on I2C

View File

@ -50,6 +50,7 @@ obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o
obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_QT1050) += qt1050.o
obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o obj-$(CONFIG_KEYBOARD_QT1070) += qt1070.o
obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o
obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o obj-$(CONFIG_KEYBOARD_SAMSUNG) += samsung-keypad.o

View File

@ -401,6 +401,8 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
if (ps2_handle_response(&atkbd->ps2dev, data)) if (ps2_handle_response(&atkbd->ps2dev, data))
goto out; goto out;
pm_wakeup_event(&serio->dev, 0);
if (!atkbd->enabled) if (!atkbd->enabled)
goto out; goto out;

View File

@ -0,0 +1,598 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Microchip AT42QT1050 QTouch Sensor Controller
*
* Copyright (C) 2019 Pengutronix, Marco Felsch <kernel@pengutronix.de>
*
* Base on AT42QT1070 driver by:
* Bo Shen <voice.shen@atmel.com>
* Copyright (C) 2011 Atmel
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
/* Chip ID */
#define QT1050_CHIP_ID 0x00
#define QT1050_CHIP_ID_VER 0x46
/* Firmware version */
#define QT1050_FW_VERSION 0x01
/* Detection status */
#define QT1050_DET_STATUS 0x02
/* Key status */
#define QT1050_KEY_STATUS 0x03
/* Key Signals */
#define QT1050_KEY_SIGNAL_0_MSB 0x06
#define QT1050_KEY_SIGNAL_0_LSB 0x07
#define QT1050_KEY_SIGNAL_1_MSB 0x08
#define QT1050_KEY_SIGNAL_1_LSB 0x09
#define QT1050_KEY_SIGNAL_2_MSB 0x0c
#define QT1050_KEY_SIGNAL_2_LSB 0x0d
#define QT1050_KEY_SIGNAL_3_MSB 0x0e
#define QT1050_KEY_SIGNAL_3_LSB 0x0f
#define QT1050_KEY_SIGNAL_4_MSB 0x10
#define QT1050_KEY_SIGNAL_4_LSB 0x11
/* Reference data */
#define QT1050_REF_DATA_0_MSB 0x14
#define QT1050_REF_DATA_0_LSB 0x15
#define QT1050_REF_DATA_1_MSB 0x16
#define QT1050_REF_DATA_1_LSB 0x17
#define QT1050_REF_DATA_2_MSB 0x1a
#define QT1050_REF_DATA_2_LSB 0x1b
#define QT1050_REF_DATA_3_MSB 0x1c
#define QT1050_REF_DATA_3_LSB 0x1d
#define QT1050_REF_DATA_4_MSB 0x1e
#define QT1050_REF_DATA_4_LSB 0x1f
/* Negative threshold level */
#define QT1050_NTHR_0 0x21
#define QT1050_NTHR_1 0x22
#define QT1050_NTHR_2 0x24
#define QT1050_NTHR_3 0x25
#define QT1050_NTHR_4 0x26
/* Pulse / Scale */
#define QT1050_PULSE_SCALE_0 0x28
#define QT1050_PULSE_SCALE_1 0x29
#define QT1050_PULSE_SCALE_2 0x2b
#define QT1050_PULSE_SCALE_3 0x2c
#define QT1050_PULSE_SCALE_4 0x2d
/* Detection integrator counter / AKS */
#define QT1050_DI_AKS_0 0x2f
#define QT1050_DI_AKS_1 0x30
#define QT1050_DI_AKS_2 0x32
#define QT1050_DI_AKS_3 0x33
#define QT1050_DI_AKS_4 0x34
/* Charge Share Delay */
#define QT1050_CSD_0 0x36
#define QT1050_CSD_1 0x37
#define QT1050_CSD_2 0x39
#define QT1050_CSD_3 0x3a
#define QT1050_CSD_4 0x3b
/* Low Power Mode */
#define QT1050_LPMODE 0x3d
/* Calibration and Reset */
#define QT1050_RES_CAL 0x3f
#define QT1050_RES_CAL_RESET BIT(7)
#define QT1050_RES_CAL_CALIBRATE BIT(1)
#define QT1050_MAX_KEYS 5
#define QT1050_RESET_TIME 255
struct qt1050_key_regs {
unsigned int nthr;
unsigned int pulse_scale;
unsigned int di_aks;
unsigned int csd;
};
struct qt1050_key {
u32 num;
u32 charge_delay;
u32 thr_cnt;
u32 samples;
u32 scale;
u32 keycode;
};
struct qt1050_priv {
struct i2c_client *client;
struct input_dev *input;
struct regmap *regmap;
struct qt1050_key keys[QT1050_MAX_KEYS];
unsigned short keycodes[QT1050_MAX_KEYS];
u8 reg_keys;
u8 last_keys;
};
static const struct qt1050_key_regs qt1050_key_regs_data[] = {
{
.nthr = QT1050_NTHR_0,
.pulse_scale = QT1050_PULSE_SCALE_0,
.di_aks = QT1050_DI_AKS_0,
.csd = QT1050_CSD_0,
}, {
.nthr = QT1050_NTHR_1,
.pulse_scale = QT1050_PULSE_SCALE_1,
.di_aks = QT1050_DI_AKS_1,
.csd = QT1050_CSD_1,
}, {
.nthr = QT1050_NTHR_2,
.pulse_scale = QT1050_PULSE_SCALE_2,
.di_aks = QT1050_DI_AKS_2,
.csd = QT1050_CSD_2,
}, {
.nthr = QT1050_NTHR_3,
.pulse_scale = QT1050_PULSE_SCALE_3,
.di_aks = QT1050_DI_AKS_3,
.csd = QT1050_CSD_3,
}, {
.nthr = QT1050_NTHR_4,
.pulse_scale = QT1050_PULSE_SCALE_4,
.di_aks = QT1050_DI_AKS_4,
.csd = QT1050_CSD_4,
}
};
static bool qt1050_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
case QT1050_DET_STATUS:
case QT1050_KEY_STATUS:
case QT1050_KEY_SIGNAL_0_MSB:
case QT1050_KEY_SIGNAL_0_LSB:
case QT1050_KEY_SIGNAL_1_MSB:
case QT1050_KEY_SIGNAL_1_LSB:
case QT1050_KEY_SIGNAL_2_MSB:
case QT1050_KEY_SIGNAL_2_LSB:
case QT1050_KEY_SIGNAL_3_MSB:
case QT1050_KEY_SIGNAL_3_LSB:
case QT1050_KEY_SIGNAL_4_MSB:
case QT1050_KEY_SIGNAL_4_LSB:
return true;
default:
return false;
}
}
static const struct regmap_range qt1050_readable_ranges[] = {
regmap_reg_range(QT1050_CHIP_ID, QT1050_KEY_STATUS),
regmap_reg_range(QT1050_KEY_SIGNAL_0_MSB, QT1050_KEY_SIGNAL_1_LSB),
regmap_reg_range(QT1050_KEY_SIGNAL_2_MSB, QT1050_KEY_SIGNAL_4_LSB),
regmap_reg_range(QT1050_REF_DATA_0_MSB, QT1050_REF_DATA_1_LSB),
regmap_reg_range(QT1050_REF_DATA_2_MSB, QT1050_REF_DATA_4_LSB),
regmap_reg_range(QT1050_NTHR_0, QT1050_NTHR_1),
regmap_reg_range(QT1050_NTHR_2, QT1050_NTHR_4),
regmap_reg_range(QT1050_PULSE_SCALE_0, QT1050_PULSE_SCALE_1),
regmap_reg_range(QT1050_PULSE_SCALE_2, QT1050_PULSE_SCALE_4),
regmap_reg_range(QT1050_DI_AKS_0, QT1050_DI_AKS_1),
regmap_reg_range(QT1050_DI_AKS_2, QT1050_DI_AKS_4),
regmap_reg_range(QT1050_CSD_0, QT1050_CSD_1),
regmap_reg_range(QT1050_CSD_2, QT1050_RES_CAL),
};
static const struct regmap_access_table qt1050_readable_table = {
.yes_ranges = qt1050_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(qt1050_readable_ranges),
};
static const struct regmap_range qt1050_writeable_ranges[] = {
regmap_reg_range(QT1050_NTHR_0, QT1050_NTHR_1),
regmap_reg_range(QT1050_NTHR_2, QT1050_NTHR_4),
regmap_reg_range(QT1050_PULSE_SCALE_0, QT1050_PULSE_SCALE_1),
regmap_reg_range(QT1050_PULSE_SCALE_2, QT1050_PULSE_SCALE_4),
regmap_reg_range(QT1050_DI_AKS_0, QT1050_DI_AKS_1),
regmap_reg_range(QT1050_DI_AKS_2, QT1050_DI_AKS_4),
regmap_reg_range(QT1050_CSD_0, QT1050_CSD_1),
regmap_reg_range(QT1050_CSD_2, QT1050_RES_CAL),
};
static const struct regmap_access_table qt1050_writeable_table = {
.yes_ranges = qt1050_writeable_ranges,
.n_yes_ranges = ARRAY_SIZE(qt1050_writeable_ranges),
};
static struct regmap_config qt1050_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = QT1050_RES_CAL,
.cache_type = REGCACHE_RBTREE,
.wr_table = &qt1050_writeable_table,
.rd_table = &qt1050_readable_table,
.volatile_reg = qt1050_volatile_reg,
};
static bool qt1050_identify(struct qt1050_priv *ts)
{
unsigned int val;
int err;
/* Read Chip ID */
regmap_read(ts->regmap, QT1050_CHIP_ID, &val);
if (val != QT1050_CHIP_ID_VER) {
dev_err(&ts->client->dev, "ID %d not supported\n", val);
return false;
}
/* Read firmware version */
err = regmap_read(ts->regmap, QT1050_FW_VERSION, &val);
if (err) {
dev_err(&ts->client->dev, "could not read the firmware version\n");
return false;
}
dev_info(&ts->client->dev, "AT42QT1050 firmware version %1d.%1d\n",
val >> 4, val & 0xf);
return true;
}
static irqreturn_t qt1050_irq_threaded(int irq, void *dev_id)
{
struct qt1050_priv *ts = dev_id;
struct input_dev *input = ts->input;
unsigned long new_keys, changed;
unsigned int val;
int i, err;
/* Read the detected status register, thus clearing interrupt */
err = regmap_read(ts->regmap, QT1050_DET_STATUS, &val);
if (err) {
dev_err(&ts->client->dev, "Fail to read detection status: %d\n",
err);
return IRQ_NONE;
}
/* Read which key changed, keys are not continuous */
err = regmap_read(ts->regmap, QT1050_KEY_STATUS, &val);
if (err) {
dev_err(&ts->client->dev,
"Fail to determine the key status: %d\n", err);
return IRQ_NONE;
}
new_keys = (val & 0x70) >> 2 | (val & 0x6) >> 1;
changed = ts->last_keys ^ new_keys;
/* Report registered keys only */
changed &= ts->reg_keys;
for_each_set_bit(i, &changed, QT1050_MAX_KEYS)
input_report_key(input, ts->keys[i].keycode,
test_bit(i, &new_keys));
ts->last_keys = new_keys;
input_sync(input);
return IRQ_HANDLED;
}
static const struct qt1050_key_regs *qt1050_get_key_regs(int key_num)
{
return &qt1050_key_regs_data[key_num];
}
static int qt1050_set_key(struct regmap *map, int number, int on)
{
const struct qt1050_key_regs *key_regs;
key_regs = qt1050_get_key_regs(number);
return regmap_update_bits(map, key_regs->di_aks, 0xfc,
on ? BIT(4) : 0x00);
}
static int qt1050_apply_fw_data(struct qt1050_priv *ts)
{
struct regmap *map = ts->regmap;
struct qt1050_key *button = &ts->keys[0];
const struct qt1050_key_regs *key_regs;
int i, err;
/* Disable all keys and enable only the specified ones */
for (i = 0; i < QT1050_MAX_KEYS; i++) {
err = qt1050_set_key(map, i, 0);
if (err)
return err;
}
for (i = 0; i < QT1050_MAX_KEYS; i++, button++) {
/* Keep KEY_RESERVED keys off */
if (button->keycode == KEY_RESERVED)
continue;
err = qt1050_set_key(map, button->num, 1);
if (err)
return err;
key_regs = qt1050_get_key_regs(button->num);
err = regmap_write(map, key_regs->pulse_scale,
(button->samples << 4) | (button->scale));
if (err)
return err;
err = regmap_write(map, key_regs->csd, button->charge_delay);
if (err)
return err;
err = regmap_write(map, key_regs->nthr, button->thr_cnt);
if (err)
return err;
}
return 0;
}
static int qt1050_parse_fw(struct qt1050_priv *ts)
{
struct device *dev = &ts->client->dev;
struct fwnode_handle *child;
int nbuttons;
nbuttons = device_get_child_node_count(dev);
if (nbuttons == 0 || nbuttons > QT1050_MAX_KEYS)
return -ENODEV;
device_for_each_child_node(dev, child) {
struct qt1050_key button;
/* Required properties */
if (fwnode_property_read_u32(child, "linux,code",
&button.keycode)) {
dev_err(dev, "Button without keycode\n");
goto err;
}
if (button.keycode >= KEY_MAX) {
dev_err(dev, "Invalid keycode 0x%x\n",
button.keycode);
goto err;
}
if (fwnode_property_read_u32(child, "reg",
&button.num)) {
dev_err(dev, "Button without pad number\n");
goto err;
}
if (button.num < 0 || button.num > QT1050_MAX_KEYS - 1)
goto err;
ts->reg_keys |= BIT(button.num);
/* Optional properties */
if (fwnode_property_read_u32(child,
"microchip,pre-charge-time-ns",
&button.charge_delay)) {
button.charge_delay = 0;
} else {
if (button.charge_delay % 2500 == 0)
button.charge_delay =
button.charge_delay / 2500;
else
button.charge_delay = 0;
}
if (fwnode_property_read_u32(child, "microchip,average-samples",
&button.samples)) {
button.samples = 0;
} else {
if (is_power_of_2(button.samples))
button.samples = ilog2(button.samples);
else
button.samples = 0;
}
if (fwnode_property_read_u32(child, "microchip,average-scaling",
&button.scale)) {
button.scale = 0;
} else {
if (is_power_of_2(button.scale))
button.scale = ilog2(button.scale);
else
button.scale = 0;
}
if (fwnode_property_read_u32(child, "microchip,threshold",
&button.thr_cnt)) {
button.thr_cnt = 20;
} else {
if (button.thr_cnt > 255)
button.thr_cnt = 20;
}
ts->keys[button.num] = button;
}
return 0;
err:
fwnode_handle_put(child);
return -EINVAL;
}
static int qt1050_probe(struct i2c_client *client)
{
struct qt1050_priv *ts;
struct input_dev *input;
struct device *dev = &client->dev;
struct regmap *map;
unsigned int status, i;
int err;
/* Check basic functionality */
err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
if (!err) {
dev_err(&client->dev, "%s adapter not supported\n",
dev_driver_string(&client->adapter->dev));
return -ENODEV;
}
if (!client->irq) {
dev_err(dev, "assign a irq line to this device\n");
return -EINVAL;
}
ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
if (!ts)
return -ENOMEM;
input = devm_input_allocate_device(dev);
if (!input)
return -ENOMEM;
map = devm_regmap_init_i2c(client, &qt1050_regmap_config);
if (IS_ERR(map))
return PTR_ERR(map);
ts->client = client;
ts->input = input;
ts->regmap = map;
i2c_set_clientdata(client, ts);
/* Identify the qt1050 chip */
if (!qt1050_identify(ts))
return -ENODEV;
/* Get pdata */
err = qt1050_parse_fw(ts);
if (err) {
dev_err(dev, "Failed to parse firmware: %d\n", err);
return err;
}
input->name = "AT42QT1050 QTouch Sensor";
input->dev.parent = &client->dev;
input->id.bustype = BUS_I2C;
/* Add the keycode */
input->keycode = ts->keycodes;
input->keycodesize = sizeof(ts->keycodes[0]);
input->keycodemax = QT1050_MAX_KEYS;
__set_bit(EV_KEY, input->evbit);
for (i = 0; i < QT1050_MAX_KEYS; i++) {
ts->keycodes[i] = ts->keys[i].keycode;
__set_bit(ts->keycodes[i], input->keybit);
}
/* Trigger re-calibration */
err = regmap_update_bits(ts->regmap, QT1050_RES_CAL, 0x7f,
QT1050_RES_CAL_CALIBRATE);
if (err) {
dev_err(dev, "Trigger calibration failed: %d\n", err);
return err;
}
err = regmap_read_poll_timeout(ts->regmap, QT1050_DET_STATUS, status,
status >> 7 == 1, 10000, 200000);
if (err) {
dev_err(dev, "Calibration failed: %d\n", err);
return err;
}
/* Soft reset to set defaults */
err = regmap_update_bits(ts->regmap, QT1050_RES_CAL,
QT1050_RES_CAL_RESET, QT1050_RES_CAL_RESET);
if (err) {
dev_err(dev, "Trigger soft reset failed: %d\n", err);
return err;
}
msleep(QT1050_RESET_TIME);
/* Set pdata */
err = qt1050_apply_fw_data(ts);
if (err) {
dev_err(dev, "Failed to set firmware data: %d\n", err);
return err;
}
err = devm_request_threaded_irq(dev, client->irq, NULL,
qt1050_irq_threaded, IRQF_ONESHOT,
"qt1050", ts);
if (err) {
dev_err(&client->dev, "Failed to request irq: %d\n", err);
return err;
}
/* Clear #CHANGE line */
err = regmap_read(ts->regmap, QT1050_DET_STATUS, &status);
if (err) {
dev_err(dev, "Failed to clear #CHANGE line level: %d\n", err);
return err;
}
/* Register the input device */
err = input_register_device(ts->input);
if (err) {
dev_err(&client->dev, "Failed to register input device: %d\n",
err);
return err;
}
return 0;
}
static int __maybe_unused qt1050_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct qt1050_priv *ts = i2c_get_clientdata(client);
disable_irq(client->irq);
/*
* Set measurement interval to 1s (125 x 8ms) if wakeup is allowed
* else turn off. The 1s interval seems to be a good compromise between
* low power and response time.
*/
return regmap_write(ts->regmap, QT1050_LPMODE,
device_may_wakeup(dev) ? 125 : 0);
}
static int __maybe_unused qt1050_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct qt1050_priv *ts = i2c_get_clientdata(client);
enable_irq(client->irq);
/* Set measurement interval back to 16ms (2 x 8ms) */
return regmap_write(ts->regmap, QT1050_LPMODE, 2);
}
static SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume);
static const struct of_device_id __maybe_unused qt1050_of_match[] = {
{ .compatible = "microchip,qt1050", },
{ },
};
MODULE_DEVICE_TABLE(of, qt1050_of_match);
static struct i2c_driver qt1050_driver = {
.driver = {
.name = "qt1050",
.of_match_table = of_match_ptr(qt1050_of_match),
.pm = &qt1050_pm_ops,
},
.probe_new = qt1050_probe,
};
module_i2c_driver(qt1050_driver);
MODULE_AUTHOR("Marco Felsch <kernel@pengutronix.de");
MODULE_DESCRIPTION("Driver for AT42QT1050 QTouch sensor");
MODULE_LICENSE("GPL v2");

View File

@ -15,6 +15,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
@ -167,28 +168,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
} }
device_init_wakeup(&pdev->dev, pdata->wakeup); device_init_wakeup(&pdev->dev, pdata->wakeup);
error = dev_pm_set_wake_irq(&pdev->dev, pdata->irq);
return 0; if (error)
} dev_err(&pdev->dev, "irq wake enable failed.\n");
static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(pdata->irq);
return 0;
}
static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(pdata->irq);
return 0; return 0;
} }
@ -199,13 +181,9 @@ static const struct of_device_id imx_snvs_pwrkey_ids[] = {
}; };
MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids); MODULE_DEVICE_TABLE(of, imx_snvs_pwrkey_ids);
static SIMPLE_DEV_PM_OPS(imx_snvs_pwrkey_pm_ops, imx_snvs_pwrkey_suspend,
imx_snvs_pwrkey_resume);
static struct platform_driver imx_snvs_pwrkey_driver = { static struct platform_driver imx_snvs_pwrkey_driver = {
.driver = { .driver = {
.name = "snvs_pwrkey", .name = "snvs_pwrkey",
.pm = &imx_snvs_pwrkey_pm_ops,
.of_match_table = imx_snvs_pwrkey_ids, .of_match_table = imx_snvs_pwrkey_ids,
}, },
.probe = imx_snvs_pwrkey_probe, .probe = imx_snvs_pwrkey_probe,

View File

@ -46,6 +46,7 @@
#define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */ #define CONTINUE_TIME_SEL(x) ((x) << 16) /* 4 bits */
#define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */ #define KEY_MODE_SEL(x) ((x) << 12) /* 2 bits */
#define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */ #define LEVELA_B_CNT(x) ((x) << 8) /* 4 bits */
#define HOLD_KEY_EN(x) ((x) << 7)
#define HOLD_EN(x) ((x) << 6) #define HOLD_EN(x) ((x) << 6)
#define LEVELB_VOL(x) ((x) << 4) /* 2 bits */ #define LEVELB_VOL(x) ((x) << 4) /* 2 bits */
#define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */ #define SAMPLE_RATE(x) ((x) << 2) /* 2 bits */
@ -63,6 +64,25 @@
#define CHAN0_KEYDOWN_IRQ BIT(1) #define CHAN0_KEYDOWN_IRQ BIT(1)
#define CHAN0_DATA_IRQ BIT(0) #define CHAN0_DATA_IRQ BIT(0)
/* struct lradc_variant - Describe sun4i-a10-lradc-keys hardware variant
* @divisor_numerator: The numerator of lradc Vref internally divisor
* @divisor_denominator: The denominator of lradc Vref internally divisor
*/
struct lradc_variant {
u8 divisor_numerator;
u8 divisor_denominator;
};
static const struct lradc_variant lradc_variant_a10 = {
.divisor_numerator = 2,
.divisor_denominator = 3
};
static const struct lradc_variant r_lradc_variant_a83t = {
.divisor_numerator = 3,
.divisor_denominator = 4
};
struct sun4i_lradc_keymap { struct sun4i_lradc_keymap {
u32 voltage; u32 voltage;
u32 keycode; u32 keycode;
@ -74,6 +94,7 @@ struct sun4i_lradc_data {
void __iomem *base; void __iomem *base;
struct regulator *vref_supply; struct regulator *vref_supply;
struct sun4i_lradc_keymap *chan0_map; struct sun4i_lradc_keymap *chan0_map;
const struct lradc_variant *variant;
u32 chan0_map_count; u32 chan0_map_count;
u32 chan0_keycode; u32 chan0_keycode;
u32 vref; u32 vref;
@ -128,9 +149,9 @@ static int sun4i_lradc_open(struct input_dev *dev)
if (error) if (error)
return error; return error;
/* lradc Vref internally is divided by 2/3 */ lradc->vref = regulator_get_voltage(lradc->vref_supply) *
lradc->vref = regulator_get_voltage(lradc->vref_supply) * 2 / 3; lradc->variant->divisor_numerator /
lradc->variant->divisor_denominator;
/* /*
* Set sample time to 4 ms / 250 Hz. Wait 2 * 4 ms for key to * Set sample time to 4 ms / 250 Hz. Wait 2 * 4 ms for key to
* stabilize on press, wait (1 + 1) * 4 ms for key release * stabilize on press, wait (1 + 1) * 4 ms for key release
@ -222,6 +243,12 @@ static int sun4i_lradc_probe(struct platform_device *pdev)
if (error) if (error)
return error; return error;
lradc->variant = of_device_get_match_data(&pdev->dev);
if (!lradc->variant) {
dev_err(&pdev->dev, "Missing sun4i-a10-lradc-keys variant\n");
return -EINVAL;
}
lradc->vref_supply = devm_regulator_get(dev, "vref"); lradc->vref_supply = devm_regulator_get(dev, "vref");
if (IS_ERR(lradc->vref_supply)) if (IS_ERR(lradc->vref_supply))
return PTR_ERR(lradc->vref_supply); return PTR_ERR(lradc->vref_supply);
@ -265,7 +292,10 @@ static int sun4i_lradc_probe(struct platform_device *pdev)
} }
static const struct of_device_id sun4i_lradc_of_match[] = { static const struct of_device_id sun4i_lradc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-lradc-keys", }, { .compatible = "allwinner,sun4i-a10-lradc-keys",
.data = &lradc_variant_a10 },
{ .compatible = "allwinner,sun8i-a83t-r-lradc",
.data = &r_lradc_variant_a83t },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match); MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match);

View File

@ -290,6 +290,18 @@ config INPUT_GPIO_DECODER
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called gpio_decoder. will be called gpio_decoder.
config INPUT_GPIO_VIBRA
tristate "GPIO vibrator support"
depends on GPIOLIB || COMPILE_TEST
select INPUT_FF_MEMLESS
help
Say Y here to get support for GPIO based vibrator devices.
If unsure, say N.
To compile this driver as a module, choose M here: the module will be
called gpio-vibra.
config INPUT_IXP4XX_BEEPER config INPUT_IXP4XX_BEEPER
tristate "IXP4XX Beeper support" tristate "IXP4XX Beeper support"
depends on ARCH_IXP4XX depends on ARCH_IXP4XX

View File

@ -36,6 +36,7 @@ obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o
obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o
obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o obj-$(CONFIG_INPUT_GPIO_DECODER) += gpio_decoder.o
obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o
obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o obj-$(CONFIG_INPUT_HISI_POWERKEY) += hisi_powerkey.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o

View File

@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* GPIO vibrator driver
*
* Copyright (C) 2019 Luca Weiss <luca@z3ntu.xyz>
*
* Based on PWM vibrator driver:
* Copyright (C) 2017 Collabora Ltd.
*
* Based on previous work from:
* Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com>
*
* Based on PWM beeper driver:
* 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>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
struct gpio_vibrator {
struct input_dev *input;
struct gpio_desc *gpio;
struct regulator *vcc;
struct work_struct play_work;
bool running;
bool vcc_on;
};
static int gpio_vibrator_start(struct gpio_vibrator *vibrator)
{
struct device *pdev = vibrator->input->dev.parent;
int err;
if (!vibrator->vcc_on) {
err = regulator_enable(vibrator->vcc);
if (err) {
dev_err(pdev, "failed to enable regulator: %d\n", err);
return err;
}
vibrator->vcc_on = true;
}
gpiod_set_value_cansleep(vibrator->gpio, 1);
return 0;
}
static void gpio_vibrator_stop(struct gpio_vibrator *vibrator)
{
gpiod_set_value_cansleep(vibrator->gpio, 0);
if (vibrator->vcc_on) {
regulator_disable(vibrator->vcc);
vibrator->vcc_on = false;
}
}
static void gpio_vibrator_play_work(struct work_struct *work)
{
struct gpio_vibrator *vibrator =
container_of(work, struct gpio_vibrator, play_work);
if (vibrator->running)
gpio_vibrator_start(vibrator);
else
gpio_vibrator_stop(vibrator);
}
static int gpio_vibrator_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
struct gpio_vibrator *vibrator = input_get_drvdata(dev);
int level;
level = effect->u.rumble.strong_magnitude;
if (!level)
level = effect->u.rumble.weak_magnitude;
vibrator->running = level;
schedule_work(&vibrator->play_work);
return 0;
}
static void gpio_vibrator_close(struct input_dev *input)
{
struct gpio_vibrator *vibrator = input_get_drvdata(input);
cancel_work_sync(&vibrator->play_work);
gpio_vibrator_stop(vibrator);
vibrator->running = false;
}
static int gpio_vibrator_probe(struct platform_device *pdev)
{
struct gpio_vibrator *vibrator;
int err;
vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL);
if (!vibrator)
return -ENOMEM;
vibrator->input = devm_input_allocate_device(&pdev->dev);
if (!vibrator->input)
return -ENOMEM;
vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc");
err = PTR_ERR_OR_ZERO(vibrator->vcc);
if (err) {
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev, "Failed to request regulator: %d\n",
err);
return err;
}
vibrator->gpio = devm_gpiod_get(&pdev->dev, "enable", GPIOD_OUT_LOW);
err = PTR_ERR_OR_ZERO(vibrator->gpio);
if (err) {
if (err != -EPROBE_DEFER)
dev_err(&pdev->dev, "Failed to request main gpio: %d\n",
err);
return err;
}
INIT_WORK(&vibrator->play_work, gpio_vibrator_play_work);
vibrator->input->name = "gpio-vibrator";
vibrator->input->id.bustype = BUS_HOST;
vibrator->input->close = gpio_vibrator_close;
input_set_drvdata(vibrator->input, vibrator);
input_set_capability(vibrator->input, EV_FF, FF_RUMBLE);
err = input_ff_create_memless(vibrator->input, NULL,
gpio_vibrator_play_effect);
if (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\n", err);
return err;
}
platform_set_drvdata(pdev, vibrator);
return 0;
}
static int __maybe_unused gpio_vibrator_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gpio_vibrator *vibrator = platform_get_drvdata(pdev);
cancel_work_sync(&vibrator->play_work);
if (vibrator->running)
gpio_vibrator_stop(vibrator);
return 0;
}
static int __maybe_unused gpio_vibrator_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gpio_vibrator *vibrator = platform_get_drvdata(pdev);
if (vibrator->running)
gpio_vibrator_start(vibrator);
return 0;
}
static SIMPLE_DEV_PM_OPS(gpio_vibrator_pm_ops,
gpio_vibrator_suspend, gpio_vibrator_resume);
#ifdef CONFIG_OF
static const struct of_device_id gpio_vibra_dt_match_table[] = {
{ .compatible = "gpio-vibrator" },
{}
};
MODULE_DEVICE_TABLE(of, gpio_vibra_dt_match_table);
#endif
static struct platform_driver gpio_vibrator_driver = {
.probe = gpio_vibrator_probe,
.driver = {
.name = "gpio-vibrator",
.pm = &gpio_vibrator_pm_ops,
.of_match_table = of_match_ptr(gpio_vibra_dt_match_table),
},
};
module_platform_driver(gpio_vibrator_driver);
MODULE_AUTHOR("Luca Weiss <luca@z3ntu.xy>");
MODULE_DESCRIPTION("GPIO vibrator driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-vibrator");

View File

@ -373,6 +373,8 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (ps2_handle_response(&psmouse->ps2dev, data)) if (ps2_handle_response(&psmouse->ps2dev, data))
goto out; goto out;
pm_wakeup_event(&serio->dev, 0);
if (psmouse->state <= PSMOUSE_RESYNCING) if (psmouse->state <= PSMOUSE_RESYNCING)
goto out; goto out;

View File

@ -456,25 +456,15 @@ static int rmi_f54_vidioc_fmt(struct file *file, void *priv,
static int rmi_f54_vidioc_enum_fmt(struct file *file, void *priv, static int rmi_f54_vidioc_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmt) struct v4l2_fmtdesc *fmt)
{ {
struct f54_data *f54 = video_drvdata(file);
if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
switch (fmt->index) { if (fmt->index)
case 0:
fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
break;
case 1:
fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD08;
break;
case 2:
fmt->pixelformat = V4L2_TCH_FMT_TU16;
break;
default:
return -EINVAL; return -EINVAL;
}
fmt->pixelformat = f54->format.pixelformat;
return 0; return 0;
} }
@ -692,6 +682,7 @@ static int rmi_f54_probe(struct rmi_function *fn)
return -ENOMEM; return -ENOMEM;
rmi_f54_create_input_map(f54); rmi_f54_create_input_map(f54);
rmi_f54_set_input(f54, 0);
/* register video device */ /* register video device */
strlcpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name)); strlcpy(f54->v4l2.name, F54_NAME, sizeof(f54->v4l2.name));

View File

@ -254,6 +254,7 @@ config SERIO_APBPS2
config SERIO_OLPC_APSP config SERIO_OLPC_APSP
tristate "OLPC AP-SP input support" tristate "OLPC AP-SP input support"
depends on ARCH_MMP || COMPILE_TEST
help help
Say Y here if you want support for the keyboard and touchpad included Say Y here if you want support for the keyboard and touchpad included
in the OLPC XO-1.75 and XO-4 laptops. in the OLPC XO-1.75 and XO-4 laptops.

View File

@ -440,5 +440,7 @@ static void __exit hv_kbd_exit(void)
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Keyboard Driver");
module_init(hv_kbd_init); module_init(hv_kbd_init);
module_exit(hv_kbd_exit); module_exit(hv_kbd_exit);

View File

@ -573,9 +573,6 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
port = &i8042_ports[port_no]; port = &i8042_ports[port_no];
serio = port->exists ? port->serio : NULL; serio = port->exists ? port->serio : NULL;
if (irq && serio)
pm_wakeup_event(&serio->dev, 0);
filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n", filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n",
port_no, irq, port_no, irq,
dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_PARITY ? ", bad parity" : "",

View File

@ -409,6 +409,7 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
ps2dev->nak = PS2_RET_ERR; ps2dev->nak = PS2_RET_ERR;
break; break;
} }
/* Fall through */
/* /*
* Workaround for mice which don't ACK the Get ID command. * Workaround for mice which don't ACK the Get ID command.

View File

@ -1312,4 +1312,14 @@ config TOUCHSCREEN_ROHM_BU21023
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bu21023_ts. module will be called bu21023_ts.
config TOUCHSCREEN_IQS5XX
tristate "Azoteq IQS550/572/525 trackpad/touchscreen controller"
depends on I2C
help
Say Y to enable support for the Azoteq IQS550/572/525
family of trackpad/touchscreen controllers.
To compile this driver as a module, choose M here: the
module will be called iqs5xx.
endif endif

View File

@ -110,3 +110,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW) += raspberrypi-ts.o obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW) += raspberrypi-ts.o
obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5xx.o

View File

@ -1,20 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
* Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support) * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
* Lothar Waßmann <LW@KARO-electronics.de> (DT support) * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* /*
@ -39,7 +27,6 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/input/touchscreen.h> #include <linux/input/touchscreen.h>
#include <linux/of_device.h>
#define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_THRESHOLD 0x00
#define WORK_REGISTER_REPORT_RATE 0x08 #define WORK_REGISTER_REPORT_RATE 0x08
@ -1073,7 +1060,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
} }
chip_data = of_device_get_match_data(&client->dev); chip_data = device_get_match_data(&client->dev);
if (!chip_data) if (!chip_data)
chip_data = (const struct edt_i2c_chip_data *)id->driver_data; chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
if (!chip_data || !chip_data->max_support_points) { if (!chip_data || !chip_data->max_support_points) {
@ -1254,7 +1241,6 @@ static const struct i2c_device_id edt_ft5x06_ts_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
#ifdef CONFIG_OF
static const struct of_device_id edt_ft5x06_of_match[] = { static const struct of_device_id edt_ft5x06_of_match[] = {
{ .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
{ .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
@ -1266,12 +1252,11 @@ static const struct of_device_id edt_ft5x06_of_match[] = {
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
#endif
static struct i2c_driver edt_ft5x06_ts_driver = { static struct i2c_driver edt_ft5x06_ts_driver = {
.driver = { .driver = {
.name = "edt_ft5x06", .name = "edt_ft5x06",
.of_match_table = of_match_ptr(edt_ft5x06_of_match), .of_match_table = edt_ft5x06_of_match,
.pm = &edt_ft5x06_ts_pm_ops, .pm = &edt_ft5x06_ts_pm_ops,
}, },
.id_table = edt_ft5x06_ts_id, .id_table = edt_ft5x06_ts_id,
@ -1283,4 +1268,4 @@ module_i2c_driver(edt_ft5x06_ts_driver);
MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>"); MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>");
MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver"); MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");

View File

@ -27,6 +27,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/of.h> #include <linux/of.h>
@ -47,6 +48,8 @@ struct goodix_ts_data {
struct touchscreen_properties prop; struct touchscreen_properties prop;
unsigned int max_touch_num; unsigned int max_touch_num;
unsigned int int_trigger_type; unsigned int int_trigger_type;
struct regulator *avdd28;
struct regulator *vddio;
struct gpio_desc *gpiod_int; struct gpio_desc *gpiod_int;
struct gpio_desc *gpiod_rst; struct gpio_desc *gpiod_rst;
u16 id; u16 id;
@ -216,6 +219,7 @@ static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
{ {
switch (id) { switch (id) {
case 1151: case 1151:
case 5663:
case 5688: case 5688:
return &gt1x_chip_data; return &gt1x_chip_data;
@ -532,6 +536,24 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
return -EINVAL; return -EINVAL;
dev = &ts->client->dev; dev = &ts->client->dev;
ts->avdd28 = devm_regulator_get(dev, "AVDD28");
if (IS_ERR(ts->avdd28)) {
error = PTR_ERR(ts->avdd28);
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get AVDD28 regulator: %d\n", error);
return error;
}
ts->vddio = devm_regulator_get(dev, "VDDIO");
if (IS_ERR(ts->vddio)) {
error = PTR_ERR(ts->vddio);
if (error != -EPROBE_DEFER)
dev_err(dev,
"Failed to get VDDIO regulator: %d\n", error);
return error;
}
/* Get the interrupt GPIO pin number */ /* Get the interrupt GPIO pin number */
gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
@ -764,6 +786,14 @@ static void goodix_config_cb(const struct firmware *cfg, void *ctx)
complete_all(&ts->firmware_loading_complete); complete_all(&ts->firmware_loading_complete);
} }
static void goodix_disable_regulators(void *arg)
{
struct goodix_ts_data *ts = arg;
regulator_disable(ts->vddio);
regulator_disable(ts->avdd28);
}
static int goodix_ts_probe(struct i2c_client *client, static int goodix_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
@ -789,6 +819,29 @@ static int goodix_ts_probe(struct i2c_client *client,
if (error) if (error)
return error; return error;
/* power up the controller */
error = regulator_enable(ts->avdd28);
if (error) {
dev_err(&client->dev,
"Failed to enable AVDD28 regulator: %d\n",
error);
return error;
}
error = regulator_enable(ts->vddio);
if (error) {
dev_err(&client->dev,
"Failed to enable VDDIO regulator: %d\n",
error);
regulator_disable(ts->avdd28);
return error;
}
error = devm_add_action_or_reset(&client->dev,
goodix_disable_regulators, ts);
if (error)
return error;
if (ts->gpiod_int && ts->gpiod_rst) { if (ts->gpiod_int && ts->gpiod_rst) {
/* reset the controller */ /* reset the controller */
error = goodix_reset(ts); error = goodix_reset(ts);
@ -945,6 +998,7 @@ MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id goodix_of_match[] = { static const struct of_device_id goodix_of_match[] = {
{ .compatible = "goodix,gt1151" }, { .compatible = "goodix,gt1151" },
{ .compatible = "goodix,gt5663" },
{ .compatible = "goodix,gt5688" }, { .compatible = "goodix,gt5688" },
{ .compatible = "goodix,gt911" }, { .compatible = "goodix,gt911" },
{ .compatible = "goodix,gt9110" }, { .compatible = "goodix,gt9110" },

File diff suppressed because it is too large Load Diff

View File

@ -606,6 +606,7 @@
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ #define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */