mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - updates to Ilitech driver to support ILI2117 - face lift of st1232 driver to support MT-B protocol - a new driver for i.MX system controller keys - mpr121 driver now supports polling mode - various input drivers have been switched away from input_polled_dev to use polled mode of regular input devices - other assorted cleanups and fixes * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (70 commits) Input: synaptics-rmi4 - fix various V4L2 compliance problems in F54 Input: synaptics - switch another X1 Carbon 6 to RMI/SMbus Input: fix Kconfig indentation Input: imx_sc_key - correct SCU message structure to avoid stack corruption Input: ili210x - optionally show calibrate sysfs attribute Input: ili210x - add resolution to chip operations structure Input: ili210x - do not retrieve/print chip firmware version Input: mms114 - use device_get_match_data Input: ili210x - remove unneeded suspend and resume handlers Input: ili210x - do not unconditionally mark touchscreen as wakeup source Input: ili210x - define and use chip operations structure Input: ili210x - do not set parent device explicitly Input: ili210x - handle errors from input_mt_init_slots() Input: ili210x - switch to using threaded IRQ Input: ili210x - add ILI2117 support dt-bindings: input: touchscreen: ad7879: generic node names in example Input: ar1021 - fix typo in preprocessor macro name Input: synaptics-rmi4 - simplify data read in rmi_f54_work Input: kxtj9 - switch to using polled mode of input devices Input: kxtj9 - switch to using managed resources ...
This commit is contained in:
commit
72c0870e3a
@ -157,6 +157,15 @@ Required properties:
|
||||
Optional properties:
|
||||
- timeout-sec: contains the watchdog timeout in seconds.
|
||||
|
||||
SCU key bindings based on SCU Message Protocol
|
||||
------------------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible: should be:
|
||||
"fsl,imx8qxp-sc-key"
|
||||
followed by "fsl,imx-sc-key";
|
||||
- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
|
||||
|
||||
Example (imx8qxp):
|
||||
-------------
|
||||
aliases {
|
||||
@ -220,6 +229,11 @@ firmware {
|
||||
compatible = "fsl,imx8qxp-sc-rtc";
|
||||
};
|
||||
|
||||
scu_key: scu-key {
|
||||
compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key";
|
||||
linux,keycodes = <KEY_POWER>;
|
||||
};
|
||||
|
||||
watchdog {
|
||||
compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt";
|
||||
timeout-sec = <60>;
|
||||
|
@ -0,0 +1,89 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/fsl,mpr121-touchkey.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale MPR121 capacitive touch sensor controller
|
||||
|
||||
maintainers:
|
||||
- Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
||||
|
||||
description: |
|
||||
The MPR121 supports up to 12 completely independent electrodes/capacitance
|
||||
sensing inputs in which 8 are multifunctional for LED driving and GPIO.
|
||||
https://www.nxp.com/docs/en/data-sheet/MPR121.pdf
|
||||
|
||||
allOf:
|
||||
- $ref: input.yaml#
|
||||
|
||||
anyOf:
|
||||
- required: [ interrupts ]
|
||||
- required: [ poll-interval ]
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,mpr121-touchkey
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
maxItems: 1
|
||||
|
||||
linux,keycodes:
|
||||
minItems: 1
|
||||
maxItems: 12
|
||||
|
||||
wakeup-source:
|
||||
description: Use any event on keypad as wakeup event.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- linux,keycodes
|
||||
|
||||
examples:
|
||||
- |
|
||||
// Example with interrupts
|
||||
#include "dt-bindings/input/input.h"
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mpr121@5a {
|
||||
compatible = "fsl,mpr121-touchkey";
|
||||
reg = <0x5a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <28 2>;
|
||||
autorepeat;
|
||||
vdd-supply = <&ldo4_reg>;
|
||||
linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
|
||||
<KEY_4>, <KEY_5>, <KEY_6>, <KEY_7>,
|
||||
<KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
// Example with polling
|
||||
#include "dt-bindings/input/input.h"
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
mpr121@5a {
|
||||
compatible = "fsl,mpr121-touchkey";
|
||||
reg = <0x5a>;
|
||||
poll-interval = <20>;
|
||||
autorepeat;
|
||||
vdd-supply = <&ldo4_reg>;
|
||||
linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
|
||||
<KEY_4>, <KEY_5>, <KEY_6>, <KEY_7>,
|
||||
<KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
|
||||
};
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
Ilitek ILI210x/ILI251x touchscreen controller
|
||||
Ilitek ILI210x/ILI2117/ILI251x touchscreen controller
|
||||
|
||||
Required properties:
|
||||
- compatible:
|
||||
ilitek,ili210x for ILI210x
|
||||
ilitek,ili2117 for ILI2117
|
||||
ilitek,ili251x for ILI251x
|
||||
|
||||
- reg: The I2C address of the device
|
||||
|
36
Documentation/devicetree/bindings/input/input.yaml
Normal file
36
Documentation/devicetree/bindings/input/input.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/input/input.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common input schema binding
|
||||
|
||||
maintainers:
|
||||
- Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
||||
|
||||
properties:
|
||||
autorepeat:
|
||||
description: Enable autorepeat when key is pressed and held down.
|
||||
type: boolean
|
||||
|
||||
linux,keycodes:
|
||||
description:
|
||||
Specifies an array of numeric keycode values to be used for reporting
|
||||
button presses.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
- items:
|
||||
minimum: 0
|
||||
maximum: 0xff
|
||||
|
||||
poll-interval:
|
||||
description: Poll interval time in milliseconds.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
power-off-time-sec:
|
||||
description:
|
||||
Duration in seconds which the key should be kept pressed for device to
|
||||
power off automatically. Device with key pressed shutdown feature can
|
||||
specify this property.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
@ -1,8 +0,0 @@
|
||||
General Keys Properties:
|
||||
|
||||
Optional properties for Keys:
|
||||
- power-off-time-sec: Duration in seconds which the key should be kept
|
||||
pressed for device to power off automatically. Device with key pressed
|
||||
shutdown feature can specify this property.
|
||||
- linux,keycodes: Specifies the numeric keycode values to be used for
|
||||
reporting key presses.
|
@ -1,30 +0,0 @@
|
||||
* Freescale MPR121 Controllor
|
||||
|
||||
Required Properties:
|
||||
- compatible: Should be "fsl,mpr121-touchkey"
|
||||
- reg: The I2C slave address of the device.
|
||||
- interrupts: The interrupt number to the cpu.
|
||||
- vdd-supply: Phandle to the Vdd power supply.
|
||||
- linux,keycodes: Specifies an array of numeric keycode values to
|
||||
be used for reporting button presses. The array can
|
||||
contain up to 12 entries.
|
||||
|
||||
Optional Properties:
|
||||
- wakeup-source: Use any event on keypad as wakeup event.
|
||||
- autorepeat: Enable autorepeat feature.
|
||||
|
||||
Example:
|
||||
|
||||
#include "dt-bindings/input/input.h"
|
||||
|
||||
touchkey: mpr121@5a {
|
||||
compatible = "fsl,mpr121-touchkey";
|
||||
reg = <0x5a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <28 2>;
|
||||
autorepeat;
|
||||
vdd-supply = <&ldo4_reg>;
|
||||
linux,keycodes = <KEY_0>, <KEY_1>, <KEY_2>, <KEY_3>,
|
||||
<KEY_4> <KEY_5>, <KEY_6>, <KEY_7>,
|
||||
<KEY_8>, <KEY_9>, <KEY_A>, <KEY_B>;
|
||||
};
|
@ -10,13 +10,13 @@ Documentation/devicetree/bindings/mfd/mt6397.txt
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
|
||||
- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
|
||||
- linux,keycodes: See Documentation/devicetree/bindings/input/input.yaml
|
||||
|
||||
Optional Properties:
|
||||
- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
|
||||
- mediatek,long-press-mode: Long press key shutdown setting, 1 for
|
||||
pwrkey only, 2 for pwrkey/homekey together, others for disabled.
|
||||
- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt
|
||||
- power-off-time-sec: See Documentation/devicetree/bindings/input/input.yaml
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -15,7 +15,7 @@ Optional properties:
|
||||
- st,onkey-pu-inactive: onkey pull up is not active
|
||||
- power-off-time-sec: Duration in seconds which the key should be kept
|
||||
pressed for device to power off automatically (from 1 to 16 seconds).
|
||||
see See Documentation/devicetree/bindings/input/keys.txt
|
||||
see See Documentation/devicetree/bindings/input/input.yaml
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -38,7 +38,7 @@ Optional properties:
|
||||
|
||||
Example:
|
||||
|
||||
ad7879@2c {
|
||||
touchscreen0@2c {
|
||||
compatible = "adi,ad7879-1";
|
||||
reg = <0x2c>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
@ -52,7 +52,7 @@ Example:
|
||||
adi,conversion-interval = /bits/ 8 <255>;
|
||||
};
|
||||
|
||||
ad7879@1 {
|
||||
touchscreen1@1 {
|
||||
compatible = "adi,ad7879";
|
||||
spi-max-frequency = <5000000>;
|
||||
reg = <1>;
|
||||
|
@ -30,6 +30,7 @@ Required properties:
|
||||
Optional properties:
|
||||
- reset-gpios: GPIO specification for the RESET input
|
||||
- wake-gpios: GPIO specification for the WAKE input
|
||||
- vcc-supply: Regulator that supplies the touchscreen
|
||||
|
||||
- pinctrl-names: should be "default"
|
||||
- pinctrl-0: a phandle pointing to the pin settings for the
|
||||
|
@ -123,6 +123,15 @@ void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval)
|
||||
}
|
||||
EXPORT_SYMBOL(input_set_max_poll_interval);
|
||||
|
||||
int input_get_poll_interval(struct input_dev *dev)
|
||||
{
|
||||
if (!dev->poller)
|
||||
return -EINVAL;
|
||||
|
||||
return dev->poller->poll_interval;
|
||||
}
|
||||
EXPORT_SYMBOL(input_get_poll_interval);
|
||||
|
||||
/* SYSFS interface */
|
||||
|
||||
static ssize_t input_dev_get_poll_interval(struct device *dev,
|
||||
|
@ -334,7 +334,6 @@ config JOYSTICK_MAPLE
|
||||
config JOYSTICK_PSXPAD_SPI
|
||||
tristate "PlayStation 1/2 joypads via SPI interface"
|
||||
depends on SPI
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you wish to connect PlayStation 1/2 joypads
|
||||
via SPI interface.
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
@ -60,7 +59,7 @@ static const u8 PSX_CMD_ENABLE_MOTOR[] = {
|
||||
|
||||
struct psxpad {
|
||||
struct spi_device *spi;
|
||||
struct input_polled_dev *pdev;
|
||||
struct input_dev *idev;
|
||||
char phys[0x20];
|
||||
bool motor1enable;
|
||||
bool motor2enable;
|
||||
@ -140,8 +139,7 @@ static void psxpad_set_motor_level(struct psxpad *pad,
|
||||
static int psxpad_spi_play_effect(struct input_dev *idev,
|
||||
void *data, struct ff_effect *effect)
|
||||
{
|
||||
struct input_polled_dev *pdev = input_get_drvdata(idev);
|
||||
struct psxpad *pad = pdev->private;
|
||||
struct psxpad *pad = input_get_drvdata(idev);
|
||||
|
||||
switch (effect->type) {
|
||||
case FF_RUMBLE:
|
||||
@ -158,10 +156,9 @@ static int psxpad_spi_init_ff(struct psxpad *pad)
|
||||
{
|
||||
int err;
|
||||
|
||||
input_set_capability(pad->pdev->input, EV_FF, FF_RUMBLE);
|
||||
input_set_capability(pad->idev, EV_FF, FF_RUMBLE);
|
||||
|
||||
err = input_ff_create_memless(pad->pdev->input, NULL,
|
||||
psxpad_spi_play_effect);
|
||||
err = input_ff_create_memless(pad->idev, NULL, psxpad_spi_play_effect);
|
||||
if (err) {
|
||||
dev_err(&pad->spi->dev,
|
||||
"input_ff_create_memless() failed: %d\n", err);
|
||||
@ -189,24 +186,25 @@ static inline int psxpad_spi_init_ff(struct psxpad *pad)
|
||||
}
|
||||
#endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
|
||||
|
||||
static void psxpad_spi_poll_open(struct input_polled_dev *pdev)
|
||||
static int psxpad_spi_poll_open(struct input_dev *input)
|
||||
{
|
||||
struct psxpad *pad = pdev->private;
|
||||
struct psxpad *pad = input_get_drvdata(input);
|
||||
|
||||
pm_runtime_get_sync(&pad->spi->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void psxpad_spi_poll_close(struct input_polled_dev *pdev)
|
||||
static void psxpad_spi_poll_close(struct input_dev *input)
|
||||
{
|
||||
struct psxpad *pad = pdev->private;
|
||||
struct psxpad *pad = input_get_drvdata(input);
|
||||
|
||||
pm_runtime_put_sync(&pad->spi->dev);
|
||||
}
|
||||
|
||||
static void psxpad_spi_poll(struct input_polled_dev *pdev)
|
||||
static void psxpad_spi_poll(struct input_dev *input)
|
||||
{
|
||||
struct psxpad *pad = pdev->private;
|
||||
struct input_dev *input = pdev->input;
|
||||
struct psxpad *pad = input_get_drvdata(input);
|
||||
u8 b_rsp3, b_rsp4;
|
||||
int err;
|
||||
|
||||
@ -284,7 +282,6 @@ static void psxpad_spi_poll(struct input_polled_dev *pdev)
|
||||
static int psxpad_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct psxpad *pad;
|
||||
struct input_polled_dev *pdev;
|
||||
struct input_dev *idev;
|
||||
int err;
|
||||
|
||||
@ -292,31 +289,26 @@ static int psxpad_spi_probe(struct spi_device *spi)
|
||||
if (!pad)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev = input_allocate_polled_device();
|
||||
if (!pdev) {
|
||||
idev = devm_input_allocate_device(&spi->dev);
|
||||
if (!idev) {
|
||||
dev_err(&spi->dev, "failed to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* input poll device settings */
|
||||
pad->pdev = pdev;
|
||||
pad->idev = idev;
|
||||
pad->spi = spi;
|
||||
|
||||
pdev->private = pad;
|
||||
pdev->open = psxpad_spi_poll_open;
|
||||
pdev->close = psxpad_spi_poll_close;
|
||||
pdev->poll = psxpad_spi_poll;
|
||||
/* poll interval is about 60fps */
|
||||
pdev->poll_interval = 16;
|
||||
pdev->poll_interval_min = 8;
|
||||
pdev->poll_interval_max = 32;
|
||||
|
||||
/* input device settings */
|
||||
idev = pdev->input;
|
||||
input_set_drvdata(idev, pad);
|
||||
|
||||
idev->name = "PlayStation 1/2 joypad";
|
||||
snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev));
|
||||
idev->id.bustype = BUS_SPI;
|
||||
|
||||
idev->open = psxpad_spi_poll_open;
|
||||
idev->close = psxpad_spi_poll_close;
|
||||
|
||||
/* key/value map settings */
|
||||
input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
|
||||
input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0);
|
||||
@ -354,11 +346,23 @@ static int psxpad_spi_probe(struct spi_device *spi)
|
||||
/* pad settings */
|
||||
psxpad_set_motor_level(pad, 0, 0);
|
||||
|
||||
|
||||
err = input_setup_polling(idev, psxpad_spi_poll);
|
||||
if (err) {
|
||||
dev_err(&spi->dev, "failed to set up polling: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* poll interval is about 60fps */
|
||||
input_set_poll_interval(idev, 16);
|
||||
input_set_min_poll_interval(idev, 8);
|
||||
input_set_max_poll_interval(idev, 32);
|
||||
|
||||
/* register input poll device */
|
||||
err = input_register_polled_device(pdev);
|
||||
err = input_register_device(idev);
|
||||
if (err) {
|
||||
dev_err(&spi->dev,
|
||||
"failed to register input poll device: %d\n", err);
|
||||
"failed to register input device: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ if INPUT_KEYBOARD
|
||||
config KEYBOARD_ADC
|
||||
tristate "ADC Ladder Buttons"
|
||||
depends on IIO
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
This driver implements support for buttons connected
|
||||
to an ADC using a resistor ladder.
|
||||
@ -168,14 +167,14 @@ config KEYBOARD_QT1050
|
||||
the module will be called qt1050
|
||||
|
||||
config KEYBOARD_QT1070
|
||||
tristate "Atmel AT42QT1070 Touch Sensor Chip"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to use Atmel AT42QT1070 QTouch
|
||||
Sensor chip as input device.
|
||||
tristate "Atmel AT42QT1070 Touch Sensor Chip"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if you want to use Atmel AT42QT1070 QTouch
|
||||
Sensor chip as input device.
|
||||
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called qt1070
|
||||
To compile this driver as a module, choose M here:
|
||||
the module will be called qt1070
|
||||
|
||||
config KEYBOARD_QT2160
|
||||
tristate "Atmel AT42QT2160 Touch Sensor Chip"
|
||||
@ -191,7 +190,6 @@ config KEYBOARD_CLPS711X
|
||||
tristate "CLPS711X Keypad support"
|
||||
depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
|
||||
select INPUT_MATRIXKMAP
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here to enable the matrix keypad on the Cirrus Logic
|
||||
CLPS711X CPUs.
|
||||
@ -250,7 +248,6 @@ config KEYBOARD_GPIO
|
||||
config KEYBOARD_GPIO_POLLED
|
||||
tristate "Polled GPIO buttons"
|
||||
depends on GPIOLIB
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
This driver implements support for buttons connected
|
||||
to GPIO pins that are not capable of generating interrupts.
|
||||
@ -342,7 +339,6 @@ config KEYBOARD_HIL
|
||||
config KEYBOARD_HP6XX
|
||||
tristate "HP Jornada 6xx keyboard"
|
||||
depends on SH_HP6XX
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have a HP Jornada 620/660/680/690 and want to
|
||||
support the built-in keyboard.
|
||||
@ -469,6 +465,16 @@ config KEYBOARD_IMX
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx_keypad.
|
||||
|
||||
config KEYBOARD_IMX_SC_KEY
|
||||
tristate "IMX SCU Key Driver"
|
||||
depends on IMX_SCU
|
||||
help
|
||||
This is the system controller key driver for NXP i.MX SoCs with
|
||||
system controller inside.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx_sc_key.
|
||||
|
||||
config KEYBOARD_NEWTON
|
||||
tristate "Newton keyboard"
|
||||
select SERIO
|
||||
|
@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
|
||||
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
|
||||
obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o
|
||||
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o
|
||||
obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o
|
||||
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
|
||||
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
|
||||
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <linux/iio/consumer.h>
|
||||
#include <linux/iio/types.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
@ -30,9 +29,9 @@ struct adc_keys_state {
|
||||
const struct adc_keys_button *map;
|
||||
};
|
||||
|
||||
static void adc_keys_poll(struct input_polled_dev *dev)
|
||||
static void adc_keys_poll(struct input_dev *input)
|
||||
{
|
||||
struct adc_keys_state *st = dev->private;
|
||||
struct adc_keys_state *st = input_get_drvdata(input);
|
||||
int i, value, ret;
|
||||
u32 diff, closest = 0xffffffff;
|
||||
int keycode = 0;
|
||||
@ -55,12 +54,12 @@ static void adc_keys_poll(struct input_polled_dev *dev)
|
||||
keycode = 0;
|
||||
|
||||
if (st->last_key && st->last_key != keycode)
|
||||
input_report_key(dev->input, st->last_key, 0);
|
||||
input_report_key(input, st->last_key, 0);
|
||||
|
||||
if (keycode)
|
||||
input_report_key(dev->input, keycode, 1);
|
||||
input_report_key(input, keycode, 1);
|
||||
|
||||
input_sync(dev->input);
|
||||
input_sync(input);
|
||||
st->last_key = keycode;
|
||||
}
|
||||
|
||||
@ -108,7 +107,6 @@ static int adc_keys_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct adc_keys_state *st;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
enum iio_chan_type type;
|
||||
int i, value;
|
||||
@ -145,19 +143,13 @@ static int adc_keys_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(dev);
|
||||
if (!poll_dev) {
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input) {
|
||||
dev_err(dev, "failed to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(dev, "poll-interval", &value))
|
||||
poll_dev->poll_interval = value;
|
||||
|
||||
poll_dev->poll = adc_keys_poll;
|
||||
poll_dev->private = st;
|
||||
|
||||
input = poll_dev->input;
|
||||
input_set_drvdata(input, st);
|
||||
|
||||
input->name = pdev->name;
|
||||
input->phys = "adc-keys/input0";
|
||||
@ -174,7 +166,17 @@ static int adc_keys_probe(struct platform_device *pdev)
|
||||
if (device_property_read_bool(dev, "autorepeat"))
|
||||
__set_bit(EV_REP, input->evbit);
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
|
||||
error = input_setup_polling(input, adc_keys_poll);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to set up polling: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!device_property_read_u32(dev, "poll-interval", &value))
|
||||
input_set_poll_interval(input, value);
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to register input device: %d\n", error);
|
||||
return error;
|
||||
|
@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
|
||||
input_sync(kpad->input);
|
||||
}
|
||||
|
||||
static int adp5589_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
||||
{
|
||||
struct adp5589_kpad *kpad;
|
||||
struct i2c_client *client = kpad->client;
|
||||
const struct adp5589_kpad_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
struct input_dev *input;
|
||||
unsigned int revid;
|
||||
int ret, i;
|
||||
unsigned int i;
|
||||
int error;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "no platform data?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
|
||||
if (!kpad)
|
||||
return -ENOMEM;
|
||||
|
||||
switch (id->driver_data) {
|
||||
case ADP5585_02:
|
||||
kpad->support_row5 = true;
|
||||
/* fall through */
|
||||
case ADP5585_01:
|
||||
kpad->is_adp5585 = true;
|
||||
kpad->var = &const_adp5585;
|
||||
break;
|
||||
case ADP5589:
|
||||
kpad->support_row5 = true;
|
||||
kpad->var = &const_adp5589;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
|
||||
(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
|
||||
!pdata->keymap) {
|
||||
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdata->keymapsize != kpad->var->keymapsize) {
|
||||
dev_err(&client->dev, "invalid keymapsize\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pdata->gpimap && pdata->gpimapsize) {
|
||||
dev_err(&client->dev, "invalid gpimap from pdata\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
|
||||
dev_err(&client->dev, "invalid gpimapsize\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdata->gpimapsize; i++) {
|
||||
@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client,
|
||||
if (pin < kpad->var->gpi_pin_base ||
|
||||
pin > kpad->var->gpi_pin_end) {
|
||||
dev_err(&client->dev, "invalid gpi pin data\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
|
||||
pdata->keypad_en_mask) {
|
||||
dev_err(&client->dev, "invalid gpi row/col data\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!client->irq) {
|
||||
dev_err(&client->dev, "no IRQ?\n");
|
||||
error = -EINVAL;
|
||||
goto err_free_mem;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
kpad->client = client;
|
||||
kpad->input = input;
|
||||
|
||||
ret = adp5589_read(client, ADP5589_5_ID);
|
||||
if (ret < 0) {
|
||||
error = ret;
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
|
||||
|
||||
input->name = client->name;
|
||||
input->phys = "adp5589-keys/input0";
|
||||
input->dev.parent = &client->dev;
|
||||
@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
|
||||
goto err_unreg_dev;
|
||||
}
|
||||
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unreg_dev:
|
||||
input_unregister_device(input);
|
||||
input = NULL;
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void adp5589_keypad_remove(struct adp5589_kpad *kpad)
|
||||
{
|
||||
if (kpad->input) {
|
||||
free_irq(kpad->client->irq, kpad);
|
||||
input_unregister_device(kpad->input);
|
||||
}
|
||||
}
|
||||
|
||||
static int adp5589_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct adp5589_kpad *kpad;
|
||||
const struct adp5589_kpad_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
unsigned int revid;
|
||||
int error, ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "no platform data?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
|
||||
if (!kpad)
|
||||
return -ENOMEM;
|
||||
|
||||
kpad->client = client;
|
||||
|
||||
switch (id->driver_data) {
|
||||
case ADP5585_02:
|
||||
kpad->support_row5 = true;
|
||||
/* fall through */
|
||||
case ADP5585_01:
|
||||
kpad->is_adp5585 = true;
|
||||
kpad->var = &const_adp5585;
|
||||
break;
|
||||
case ADP5589:
|
||||
kpad->support_row5 = true;
|
||||
kpad->var = &const_adp5589;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = adp5589_read(client, ADP5589_5_ID);
|
||||
if (ret < 0) {
|
||||
error = ret;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
|
||||
|
||||
if (pdata->keymapsize) {
|
||||
error = adp5589_keypad_add(kpad, revid);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
error = adp5589_setup(kpad);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
goto err_keypad_remove;
|
||||
|
||||
if (kpad->gpimapsize)
|
||||
adp5589_report_switch_state(kpad);
|
||||
|
||||
error = adp5589_gpio_add(kpad);
|
||||
if (error)
|
||||
goto err_free_irq;
|
||||
goto err_keypad_remove;
|
||||
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
i2c_set_clientdata(client, kpad);
|
||||
|
||||
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(client->irq, kpad);
|
||||
err_unreg_dev:
|
||||
input_unregister_device(input);
|
||||
input = NULL;
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
err_keypad_remove:
|
||||
adp5589_keypad_remove(kpad);
|
||||
err_free_mem:
|
||||
kfree(kpad);
|
||||
|
||||
@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
|
||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||
|
||||
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||
free_irq(client->irq, kpad);
|
||||
input_unregister_device(kpad->input);
|
||||
adp5589_keypad_remove(kpad);
|
||||
adp5589_gpio_remove(kpad);
|
||||
kfree(kpad);
|
||||
|
||||
@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
|
||||
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = kpad->client;
|
||||
|
||||
if (!kpad->input)
|
||||
return 0;
|
||||
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev)
|
||||
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = kpad->client;
|
||||
|
||||
if (!kpad->input)
|
||||
return 0;
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
disable_irq_wake(client->irq);
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -30,10 +29,10 @@ struct clps711x_keypad_data {
|
||||
struct clps711x_gpio_data *gpio_data;
|
||||
};
|
||||
|
||||
static void clps711x_keypad_poll(struct input_polled_dev *dev)
|
||||
static void clps711x_keypad_poll(struct input_dev *input)
|
||||
{
|
||||
const unsigned short *keycodes = dev->input->keycode;
|
||||
struct clps711x_keypad_data *priv = dev->private;
|
||||
const unsigned short *keycodes = input->keycode;
|
||||
struct clps711x_keypad_data *priv = input_get_drvdata(input);
|
||||
bool sync = false;
|
||||
int col, row;
|
||||
|
||||
@ -61,14 +60,14 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
|
||||
|
||||
if (state) {
|
||||
set_bit(col, data->last_state);
|
||||
input_event(dev->input, EV_MSC,
|
||||
MSC_SCAN, code);
|
||||
input_event(input,
|
||||
EV_MSC, MSC_SCAN, code);
|
||||
} else {
|
||||
clear_bit(col, data->last_state);
|
||||
}
|
||||
|
||||
if (keycodes[code])
|
||||
input_report_key(dev->input,
|
||||
input_report_key(input,
|
||||
keycodes[code], state);
|
||||
sync = true;
|
||||
}
|
||||
@ -80,7 +79,7 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
|
||||
}
|
||||
|
||||
if (sync)
|
||||
input_sync(dev->input);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static int clps711x_keypad_probe(struct platform_device *pdev)
|
||||
@ -88,7 +87,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
|
||||
struct clps711x_keypad_data *priv;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
u32 poll_interval;
|
||||
int i, err;
|
||||
|
||||
@ -125,53 +124,43 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!poll_dev)
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
poll_dev->private = priv;
|
||||
poll_dev->poll = clps711x_keypad_poll;
|
||||
poll_dev->poll_interval = poll_interval;
|
||||
poll_dev->input->name = pdev->name;
|
||||
poll_dev->input->dev.parent = dev;
|
||||
poll_dev->input->id.bustype = BUS_HOST;
|
||||
poll_dev->input->id.vendor = 0x0001;
|
||||
poll_dev->input->id.product = 0x0001;
|
||||
poll_dev->input->id.version = 0x0100;
|
||||
input_set_drvdata(input, priv);
|
||||
|
||||
input->name = pdev->name;
|
||||
input->dev.parent = dev;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->id.vendor = 0x0001;
|
||||
input->id.product = 0x0001;
|
||||
input->id.version = 0x0100;
|
||||
|
||||
err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count,
|
||||
CLPS711X_KEYPAD_COL_COUNT,
|
||||
NULL, poll_dev->input);
|
||||
NULL, input);
|
||||
if (err)
|
||||
goto out_err;
|
||||
return err;
|
||||
|
||||
input_set_capability(poll_dev->input, EV_MSC, MSC_SCAN);
|
||||
input_set_capability(input, EV_MSC, MSC_SCAN);
|
||||
if (of_property_read_bool(np, "autorepeat"))
|
||||
__set_bit(EV_REP, poll_dev->input->evbit);
|
||||
|
||||
platform_set_drvdata(pdev, poll_dev);
|
||||
__set_bit(EV_REP, input->evbit);
|
||||
|
||||
/* Set all columns to low */
|
||||
regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK,
|
||||
SYSCON1_KBDSCAN(1));
|
||||
|
||||
err = input_register_polled_device(poll_dev);
|
||||
|
||||
err = input_setup_polling(input, clps711x_keypad_poll);
|
||||
if (err)
|
||||
goto out_err;
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
input_set_poll_interval(input, poll_interval);
|
||||
|
||||
out_err:
|
||||
input_free_polled_device(poll_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int clps711x_keypad_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct input_polled_dev *poll_dev = platform_get_drvdata(pdev);
|
||||
|
||||
input_unregister_polled_device(poll_dev);
|
||||
input_free_polled_device(poll_dev);
|
||||
err = input_register_device(input);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -188,7 +177,6 @@ static struct platform_driver clps711x_keypad_driver = {
|
||||
.of_match_table = clps711x_keypad_of_match,
|
||||
},
|
||||
.probe = clps711x_keypad_probe,
|
||||
.remove = clps711x_keypad_remove,
|
||||
};
|
||||
module_platform_driver(clps711x_keypad_driver);
|
||||
|
||||
|
@ -494,10 +494,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
|
||||
spin_lock_init(&bdata->lock);
|
||||
|
||||
if (child) {
|
||||
bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL,
|
||||
child,
|
||||
GPIOD_IN,
|
||||
desc);
|
||||
bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
|
||||
NULL, GPIOD_IN, desc);
|
||||
if (IS_ERR(bdata->gpiod)) {
|
||||
error = PTR_ERR(bdata->gpiod);
|
||||
if (error == -ENOENT) {
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
@ -34,7 +33,7 @@ struct gpio_keys_button_data {
|
||||
};
|
||||
|
||||
struct gpio_keys_polled_dev {
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct device *dev;
|
||||
const struct gpio_keys_platform_data *pdata;
|
||||
unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)];
|
||||
@ -42,12 +41,11 @@ struct gpio_keys_polled_dev {
|
||||
struct gpio_keys_button_data data[0];
|
||||
};
|
||||
|
||||
static void gpio_keys_button_event(struct input_polled_dev *dev,
|
||||
static void gpio_keys_button_event(struct input_dev *input,
|
||||
const struct gpio_keys_button *button,
|
||||
int state)
|
||||
{
|
||||
struct gpio_keys_polled_dev *bdev = dev->private;
|
||||
struct input_dev *input = dev->input;
|
||||
struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
|
||||
unsigned int type = button->type ?: EV_KEY;
|
||||
|
||||
if (type == EV_REL) {
|
||||
@ -66,7 +64,7 @@ static void gpio_keys_button_event(struct input_polled_dev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
|
||||
static void gpio_keys_polled_check_state(struct input_dev *input,
|
||||
const struct gpio_keys_button *button,
|
||||
struct gpio_keys_button_data *bdata)
|
||||
{
|
||||
@ -74,10 +72,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
|
||||
|
||||
state = gpiod_get_value_cansleep(bdata->gpiod);
|
||||
if (state < 0) {
|
||||
dev_err(dev->input->dev.parent,
|
||||
dev_err(input->dev.parent,
|
||||
"failed to get gpio state: %d\n", state);
|
||||
} else {
|
||||
gpio_keys_button_event(dev, button, state);
|
||||
gpio_keys_button_event(input, button, state);
|
||||
|
||||
if (state != bdata->last_state) {
|
||||
bdata->count = 0;
|
||||
@ -86,11 +84,10 @@ static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_keys_polled_poll(struct input_polled_dev *dev)
|
||||
static void gpio_keys_polled_poll(struct input_dev *input)
|
||||
{
|
||||
struct gpio_keys_polled_dev *bdev = dev->private;
|
||||
struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
|
||||
const struct gpio_keys_platform_data *pdata = bdev->pdata;
|
||||
struct input_dev *input = dev->input;
|
||||
int i;
|
||||
|
||||
memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen));
|
||||
@ -101,10 +98,10 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
|
||||
|
||||
if (bdata->count < bdata->threshold) {
|
||||
bdata->count++;
|
||||
gpio_keys_button_event(dev, &pdata->buttons[i],
|
||||
gpio_keys_button_event(input, &pdata->buttons[i],
|
||||
bdata->last_state);
|
||||
} else {
|
||||
gpio_keys_polled_check_state(dev, &pdata->buttons[i],
|
||||
gpio_keys_polled_check_state(input, &pdata->buttons[i],
|
||||
bdata);
|
||||
}
|
||||
}
|
||||
@ -122,18 +119,20 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static void gpio_keys_polled_open(struct input_polled_dev *dev)
|
||||
static int gpio_keys_polled_open(struct input_dev *input)
|
||||
{
|
||||
struct gpio_keys_polled_dev *bdev = dev->private;
|
||||
struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
|
||||
const struct gpio_keys_platform_data *pdata = bdev->pdata;
|
||||
|
||||
if (pdata->enable)
|
||||
pdata->enable(bdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_keys_polled_close(struct input_polled_dev *dev)
|
||||
static void gpio_keys_polled_close(struct input_dev *input)
|
||||
{
|
||||
struct gpio_keys_polled_dev *bdev = dev->private;
|
||||
struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
|
||||
const struct gpio_keys_platform_data *pdata = bdev->pdata;
|
||||
|
||||
if (pdata->disable)
|
||||
@ -232,7 +231,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
struct fwnode_handle *child = NULL;
|
||||
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
|
||||
struct gpio_keys_polled_dev *bdev;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
int i;
|
||||
@ -255,19 +253,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(dev);
|
||||
if (!poll_dev) {
|
||||
dev_err(dev, "no memory for polled device\n");
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input) {
|
||||
dev_err(dev, "no memory for input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
poll_dev->private = bdev;
|
||||
poll_dev->poll = gpio_keys_polled_poll;
|
||||
poll_dev->poll_interval = pdata->poll_interval;
|
||||
poll_dev->open = gpio_keys_polled_open;
|
||||
poll_dev->close = gpio_keys_polled_close;
|
||||
|
||||
input = poll_dev->input;
|
||||
input_set_drvdata(input, bdev);
|
||||
|
||||
input->name = pdata->name ?: pdev->name;
|
||||
input->phys = DRV_NAME"/input0";
|
||||
@ -277,6 +269,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
input->id.product = 0x0001;
|
||||
input->id.version = 0x0100;
|
||||
|
||||
input->open = gpio_keys_polled_open;
|
||||
input->close = gpio_keys_polled_close;
|
||||
|
||||
__set_bit(EV_KEY, input->evbit);
|
||||
if (pdata->rep)
|
||||
__set_bit(EV_REP, input->evbit);
|
||||
@ -300,10 +295,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev,
|
||||
NULL, child,
|
||||
GPIOD_IN,
|
||||
button->desc);
|
||||
bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
|
||||
NULL, GPIOD_IN,
|
||||
button->desc);
|
||||
if (IS_ERR(bdata->gpiod)) {
|
||||
error = PTR_ERR(bdata->gpiod);
|
||||
if (error != -EPROBE_DEFER)
|
||||
@ -353,11 +347,19 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
|
||||
fwnode_handle_put(child);
|
||||
|
||||
bdev->poll_dev = poll_dev;
|
||||
bdev->input = input;
|
||||
bdev->dev = dev;
|
||||
bdev->pdata = pdata;
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_setup_polling(input, gpio_keys_polled_poll);
|
||||
if (error) {
|
||||
dev_err(dev, "unable to set up polling, err=%d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input, pdata->poll_interval);
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(dev, "unable to register polled device, err=%d\n",
|
||||
error);
|
||||
@ -366,7 +368,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
|
||||
|
||||
/* report initial state of the buttons */
|
||||
for (i = 0; i < pdata->nbuttons; i++)
|
||||
gpio_keys_polled_check_state(poll_dev, &pdata->buttons[i],
|
||||
gpio_keys_polled_check_state(input, &pdata->buttons[i],
|
||||
&bdev->data[i]);
|
||||
|
||||
input_sync(input);
|
||||
|
187
drivers/input/keyboard/imx_sc_key.c
Normal file
187
drivers/input/keyboard/imx_sc_key.c
Normal file
@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2019 NXP.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware/imx/sci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#define DEBOUNCE_TIME 30
|
||||
#define REPEAT_INTERVAL 60
|
||||
|
||||
#define SC_IRQ_BUTTON 1
|
||||
#define SC_IRQ_GROUP_WAKE 3
|
||||
|
||||
#define IMX_SC_MISC_FUNC_GET_BUTTON_STATUS 18
|
||||
|
||||
struct imx_key_drv_data {
|
||||
u32 keycode;
|
||||
bool keystate; /* true: pressed, false: released */
|
||||
struct delayed_work check_work;
|
||||
struct input_dev *input;
|
||||
struct imx_sc_ipc *key_ipc_handle;
|
||||
struct notifier_block key_notifier;
|
||||
};
|
||||
|
||||
struct imx_sc_msg_key {
|
||||
struct imx_sc_rpc_msg hdr;
|
||||
u32 state;
|
||||
};
|
||||
|
||||
static int imx_sc_key_notify(struct notifier_block *nb,
|
||||
unsigned long event, void *group)
|
||||
{
|
||||
struct imx_key_drv_data *priv =
|
||||
container_of(nb,
|
||||
struct imx_key_drv_data,
|
||||
key_notifier);
|
||||
|
||||
if ((event & SC_IRQ_BUTTON) && (*(u8 *)group == SC_IRQ_GROUP_WAKE)) {
|
||||
schedule_delayed_work(&priv->check_work,
|
||||
msecs_to_jiffies(DEBOUNCE_TIME));
|
||||
pm_wakeup_event(priv->input->dev.parent, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_sc_check_for_events(struct work_struct *work)
|
||||
{
|
||||
struct imx_key_drv_data *priv =
|
||||
container_of(work,
|
||||
struct imx_key_drv_data,
|
||||
check_work.work);
|
||||
struct input_dev *input = priv->input;
|
||||
struct imx_sc_msg_key msg;
|
||||
struct imx_sc_rpc_msg *hdr = &msg.hdr;
|
||||
bool state;
|
||||
int error;
|
||||
|
||||
hdr->ver = IMX_SC_RPC_VERSION;
|
||||
hdr->svc = IMX_SC_RPC_SVC_MISC;
|
||||
hdr->func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS;
|
||||
hdr->size = 1;
|
||||
|
||||
error = imx_scu_call_rpc(priv->key_ipc_handle, &msg, true);
|
||||
if (error) {
|
||||
dev_err(&input->dev, "read imx sc key failed, error %d\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
state = (bool)msg.state;
|
||||
|
||||
if (state ^ priv->keystate) {
|
||||
priv->keystate = state;
|
||||
input_event(input, EV_KEY, priv->keycode, state);
|
||||
input_sync(input);
|
||||
if (!priv->keystate)
|
||||
pm_relax(priv->input->dev.parent);
|
||||
}
|
||||
|
||||
if (state)
|
||||
schedule_delayed_work(&priv->check_work,
|
||||
msecs_to_jiffies(REPEAT_INTERVAL));
|
||||
}
|
||||
|
||||
static int imx_sc_key_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_key_drv_data *priv;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
error = imx_scu_get_handle(&priv->key_ipc_handle);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (device_property_read_u32(&pdev->dev, "linux,keycodes",
|
||||
&priv->keycode)) {
|
||||
dev_err(&pdev->dev, "missing linux,keycodes property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&priv->check_work, imx_sc_check_for_events);
|
||||
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input) {
|
||||
dev_err(&pdev->dev, "failed to allocate the input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input->name = pdev->name;
|
||||
input->phys = "imx-sc-key/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
|
||||
input_set_capability(input, EV_KEY, priv->keycode);
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register input device\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
priv->input = input;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
error = imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
|
||||
true);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to enable scu group irq\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
priv->key_notifier.notifier_call = imx_sc_key_notify;
|
||||
error = imx_scu_irq_register_notifier(&priv->key_notifier);
|
||||
if (error) {
|
||||
imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON,
|
||||
false);
|
||||
dev_err(&pdev->dev, "failed to register scu notifier\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_sc_key_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_key_drv_data *priv = platform_get_drvdata(pdev);
|
||||
|
||||
imx_scu_irq_group_enable(SC_IRQ_GROUP_WAKE, SC_IRQ_BUTTON, false);
|
||||
imx_scu_irq_unregister_notifier(&priv->key_notifier);
|
||||
cancel_delayed_work_sync(&priv->check_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id imx_sc_key_ids[] = {
|
||||
{ .compatible = "fsl,imx-sc-key" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_sc_key_ids);
|
||||
|
||||
static struct platform_driver imx_sc_key_driver = {
|
||||
.driver = {
|
||||
.name = "imx-sc-key",
|
||||
.of_match_table = imx_sc_key_ids,
|
||||
},
|
||||
.probe = imx_sc_key_probe,
|
||||
.remove = imx_sc_key_remove,
|
||||
};
|
||||
module_platform_driver(imx_sc_key_driver);
|
||||
|
||||
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
|
||||
MODULE_DESCRIPTION("i.MX System Controller Key Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -15,7 +15,6 @@
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -64,7 +63,7 @@ static const unsigned short jornada_scancodes[] = {
|
||||
#define JORNADA_SCAN_SIZE 18
|
||||
|
||||
struct jornadakbd {
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
unsigned short keymap[ARRAY_SIZE(jornada_scancodes)];
|
||||
unsigned char length;
|
||||
unsigned char old_scan[JORNADA_SCAN_SIZE];
|
||||
@ -73,7 +72,7 @@ struct jornadakbd {
|
||||
|
||||
static void jornada_parse_kbd(struct jornadakbd *jornadakbd)
|
||||
{
|
||||
struct input_dev *input_dev = jornadakbd->poll_dev->input;
|
||||
struct input_dev *input_dev = jornadakbd->input;
|
||||
unsigned short *keymap = jornadakbd->keymap;
|
||||
unsigned int sync_me = 0;
|
||||
unsigned int i, j;
|
||||
@ -167,9 +166,9 @@ static void jornada_scan_keyb(unsigned char *s)
|
||||
*s++ = __raw_readb(PHDR);
|
||||
}
|
||||
|
||||
static void jornadakbd680_poll(struct input_polled_dev *dev)
|
||||
static void jornadakbd680_poll(struct input_dev *input)
|
||||
{
|
||||
struct jornadakbd *jornadakbd = dev->private;
|
||||
struct jornadakbd *jornadakbd = input_get_drvdata(input);
|
||||
|
||||
jornada_scan_keyb(jornadakbd->new_scan);
|
||||
jornada_parse_kbd(jornadakbd);
|
||||
@ -179,7 +178,6 @@ static void jornadakbd680_poll(struct input_polled_dev *dev)
|
||||
static int jornada680kbd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct jornadakbd *jornadakbd;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input_dev;
|
||||
int i, error;
|
||||
|
||||
@ -188,29 +186,24 @@ static int jornada680kbd_probe(struct platform_device *pdev)
|
||||
if (!jornadakbd)
|
||||
return -ENOMEM;
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(&pdev->dev);
|
||||
if (!poll_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate polled input device\n");
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
jornadakbd->poll_dev = poll_dev;
|
||||
jornadakbd->input = input_dev;
|
||||
|
||||
memcpy(jornadakbd->keymap, jornada_scancodes,
|
||||
sizeof(jornadakbd->keymap));
|
||||
|
||||
poll_dev->private = jornadakbd;
|
||||
poll_dev->poll = jornadakbd680_poll;
|
||||
poll_dev->poll_interval = 50; /* msec */
|
||||
|
||||
input_dev = poll_dev->input;
|
||||
input_set_drvdata(input_dev, jornadakbd);
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
|
||||
input_dev->name = "HP Jornada 680 keyboard";
|
||||
input_dev->phys = "jornadakbd/input0";
|
||||
input_dev->keycode = jornadakbd->keymap;
|
||||
input_dev->keycodesize = sizeof(unsigned short);
|
||||
input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes);
|
||||
input_dev->dev.parent = &pdev->dev;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
@ -220,9 +213,17 @@ static int jornada680kbd_probe(struct platform_device *pdev)
|
||||
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
|
||||
error = input_register_polled_device(jornadakbd->poll_dev);
|
||||
error = input_setup_polling(input_dev, jornadakbd680_poll);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register polled input device\n");
|
||||
dev_err(&pdev->dev, "failed to set up polling\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input_dev, 50 /* msec */);
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register input device\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,9 @@
|
||||
/* MPR121 has 12 keys */
|
||||
#define MPR121_MAX_KEY_COUNT 12
|
||||
|
||||
#define MPR121_MIN_POLL_INTERVAL 10
|
||||
#define MPR121_MAX_POLL_INTERVAL 200
|
||||
|
||||
struct mpr121_touchkey {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input_dev;
|
||||
@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
|
||||
return vdd_supply;
|
||||
}
|
||||
|
||||
static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
|
||||
static void mpr_touchkey_report(struct input_dev *dev)
|
||||
{
|
||||
struct mpr121_touchkey *mpr121 = dev_id;
|
||||
struct i2c_client *client = mpr121->client;
|
||||
struct mpr121_touchkey *mpr121 = input_get_drvdata(dev);
|
||||
struct input_dev *input = mpr121->input_dev;
|
||||
struct i2c_client *client = mpr121->client;
|
||||
unsigned long bit_changed;
|
||||
unsigned int key_num;
|
||||
int reg;
|
||||
@ -127,14 +130,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
|
||||
reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
|
||||
if (reg < 0) {
|
||||
dev_err(&client->dev, "i2c read error [%d]\n", reg);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
reg <<= 8;
|
||||
reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
|
||||
if (reg < 0) {
|
||||
dev_err(&client->dev, "i2c read error [%d]\n", reg);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
reg &= TOUCH_STATUS_MASK;
|
||||
@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
|
||||
|
||||
}
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct mpr121_touchkey *mpr121 = dev_id;
|
||||
|
||||
mpr_touchkey_report(mpr121->input_dev);
|
||||
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client,
|
||||
int vdd_uv;
|
||||
struct mpr121_touchkey *mpr121;
|
||||
struct input_dev *input_dev;
|
||||
u32 poll_interval = 0;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
if (!client->irq) {
|
||||
dev_err(dev, "irq number should not be zero\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vdd_supply = mpr121_vdd_supply_init(dev);
|
||||
if (IS_ERR(vdd_supply))
|
||||
return PTR_ERR(vdd_supply);
|
||||
@ -274,6 +279,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
|
||||
if (device_property_read_bool(dev, "autorepeat"))
|
||||
__set_bit(EV_REP, input_dev->evbit);
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
input_set_drvdata(input_dev, mpr121);
|
||||
|
||||
input_dev->keycode = mpr121->keycodes;
|
||||
input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
|
||||
@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client,
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
mpr_touchkey_interrupt,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
dev->driver->name, mpr121);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to register interrupt\n");
|
||||
return error;
|
||||
device_property_read_u32(dev, "poll-interval", &poll_interval);
|
||||
|
||||
if (client->irq) {
|
||||
error = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
mpr_touchkey_interrupt,
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT,
|
||||
dev->driver->name, mpr121);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to register interrupt\n");
|
||||
return error;
|
||||
}
|
||||
} else if (poll_interval) {
|
||||
if (poll_interval < MPR121_MIN_POLL_INTERVAL)
|
||||
return -EINVAL;
|
||||
|
||||
if (poll_interval > MPR121_MAX_POLL_INTERVAL)
|
||||
return -EINVAL;
|
||||
|
||||
error = input_setup_polling(input_dev, mpr_touchkey_report);
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to setup polling\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input_dev, poll_interval);
|
||||
input_set_min_poll_interval(input_dev,
|
||||
MPR121_MIN_POLL_INTERVAL);
|
||||
input_set_max_poll_interval(input_dev,
|
||||
MPR121_MAX_POLL_INTERVAL);
|
||||
} else {
|
||||
dev_err(dev,
|
||||
"invalid IRQ number and polling not configured\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
|
@ -100,7 +100,6 @@ config INPUT_ATMEL_CAPTOUCH
|
||||
config INPUT_BMA150
|
||||
tristate "BMA150/SMB380 acceleration sensor support"
|
||||
depends on I2C
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have Bosch Sensortec's BMA150 or SMB380
|
||||
acceleration sensor hooked to an I2C bus.
|
||||
@ -246,7 +245,6 @@ config INPUT_MC13783_PWRBUTTON
|
||||
config INPUT_MMA8450
|
||||
tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
|
||||
depends on I2C
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you want to support Freescale's MMA8450 Accelerometer
|
||||
through I2C interface.
|
||||
@ -257,7 +255,6 @@ config INPUT_MMA8450
|
||||
config INPUT_APANEL
|
||||
tristate "Fujitsu Lifebook Application Panel buttons"
|
||||
depends on X86 && I2C && LEDS_CLASS
|
||||
select INPUT_POLLDEV
|
||||
select CHECK_SIGNATURE
|
||||
help
|
||||
Say Y here for support of the Application Panel buttons, used on
|
||||
@ -291,7 +288,6 @@ config INPUT_GPIO_BEEPER
|
||||
config INPUT_GPIO_DECODER
|
||||
tristate "Polled GPIO Decoder Input driver"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you want driver to read status of multiple GPIO
|
||||
lines and report the encoded value as an absolute integer to
|
||||
@ -327,7 +323,6 @@ config INPUT_IXP4XX_BEEPER
|
||||
config INPUT_COBALT_BTNS
|
||||
tristate "Cobalt button interface"
|
||||
depends on MIPS_COBALT
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you want to support MIPS Cobalt button interface.
|
||||
|
||||
@ -347,7 +342,6 @@ config INPUT_CPCAP_PWRBUTTON
|
||||
config INPUT_WISTRON_BTNS
|
||||
tristate "x86 Wistron laptop button interface"
|
||||
depends on X86_32
|
||||
select INPUT_POLLDEV
|
||||
select INPUT_SPARSEKMAP
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
@ -410,13 +404,6 @@ config INPUT_KXTJ9
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called kxtj9.
|
||||
|
||||
config INPUT_KXTJ9_POLLED_MODE
|
||||
bool "Enable polling mode support"
|
||||
depends on INPUT_KXTJ9
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you need accelerometer to work in polling mode.
|
||||
|
||||
config INPUT_POWERMATE
|
||||
tristate "Griffin PowerMate and Contour Jog support"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
@ -546,7 +533,6 @@ config INPUT_UINPUT
|
||||
config INPUT_SGI_BTNS
|
||||
tristate "SGI Indy/O2 volume button interface"
|
||||
depends on SGI_IP22 || SGI_IP32
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you want to support SGI Indy/O2 volume button interface.
|
||||
|
||||
@ -637,7 +623,6 @@ config INPUT_RB532_BUTTON
|
||||
tristate "Mikrotik Routerboard 532 button interface"
|
||||
depends on MIKROTIK_RB532
|
||||
depends on GPIOLIB
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you want support for the S1 button built into
|
||||
Mikrotik's Routerboard 532.
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/leds.h>
|
||||
|
||||
@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX];
|
||||
#define MAX_PANEL_KEYS 12
|
||||
|
||||
struct apanel {
|
||||
struct input_polled_dev *ipdev;
|
||||
struct input_dev *idev;
|
||||
struct i2c_client *client;
|
||||
unsigned short keymap[MAX_PANEL_KEYS];
|
||||
u16 nkeys;
|
||||
u16 nkeys;
|
||||
struct led_classdev mail_led;
|
||||
};
|
||||
|
||||
static const unsigned short apanel_keymap[MAX_PANEL_KEYS] = {
|
||||
[0] = KEY_MAIL,
|
||||
[1] = KEY_WWW,
|
||||
[2] = KEY_PROG2,
|
||||
[3] = KEY_PROG1,
|
||||
|
||||
static int apanel_probe(struct i2c_client *, const struct i2c_device_id *);
|
||||
[8] = KEY_FORWARD,
|
||||
[9] = KEY_REWIND,
|
||||
[10] = KEY_STOPCD,
|
||||
[11] = KEY_PLAYPAUSE,
|
||||
};
|
||||
|
||||
static void report_key(struct input_dev *input, unsigned keycode)
|
||||
{
|
||||
pr_debug(APANEL ": report key %#x\n", keycode);
|
||||
dev_dbg(input->dev.parent, "report key %#x\n", keycode);
|
||||
input_report_key(input, keycode, 1);
|
||||
input_sync(input);
|
||||
|
||||
@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode)
|
||||
* CD keys:
|
||||
* Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800)
|
||||
*/
|
||||
static void apanel_poll(struct input_polled_dev *ipdev)
|
||||
static void apanel_poll(struct input_dev *idev)
|
||||
{
|
||||
struct apanel *ap = ipdev->private;
|
||||
struct input_dev *idev = ipdev->input;
|
||||
struct apanel *ap = input_get_drvdata(idev);
|
||||
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
|
||||
s32 data;
|
||||
int i;
|
||||
@ -112,22 +120,76 @@ static int mail_led_set(struct led_classdev *led,
|
||||
return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
|
||||
}
|
||||
|
||||
static int apanel_remove(struct i2c_client *client)
|
||||
static int apanel_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct apanel *ap = i2c_get_clientdata(client);
|
||||
struct apanel *ap;
|
||||
struct input_dev *idev;
|
||||
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
|
||||
int i, err;
|
||||
|
||||
if (device_chip[APANEL_DEV_LED] != CHIP_NONE)
|
||||
led_classdev_unregister(&ap->mail_led);
|
||||
ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL);
|
||||
if (!ap)
|
||||
return -ENOMEM;
|
||||
|
||||
input_unregister_polled_device(ap->ipdev);
|
||||
input_free_polled_device(ap->ipdev);
|
||||
idev = devm_input_allocate_device(&client->dev);
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
|
||||
ap->idev = idev;
|
||||
ap->client = client;
|
||||
|
||||
i2c_set_clientdata(client, ap);
|
||||
|
||||
err = i2c_smbus_write_word_data(client, cmd, 0);
|
||||
if (err) {
|
||||
dev_warn(&client->dev, "smbus write error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
input_set_drvdata(idev, ap);
|
||||
|
||||
idev->name = APANEL_NAME " buttons";
|
||||
idev->phys = "apanel/input0";
|
||||
idev->id.bustype = BUS_HOST;
|
||||
|
||||
memcpy(ap->keymap, apanel_keymap, sizeof(apanel_keymap));
|
||||
idev->keycode = ap->keymap;
|
||||
idev->keycodesize = sizeof(ap->keymap[0]);
|
||||
idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4;
|
||||
|
||||
set_bit(EV_KEY, idev->evbit);
|
||||
for (i = 0; i < idev->keycodemax; i++)
|
||||
if (ap->keymap[i])
|
||||
set_bit(ap->keymap[i], idev->keybit);
|
||||
|
||||
err = input_setup_polling(idev, apanel_poll);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
input_set_poll_interval(idev, POLL_INTERVAL_DEFAULT);
|
||||
|
||||
err = input_register_device(idev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
|
||||
ap->mail_led.name = "mail:blue";
|
||||
ap->mail_led.brightness_set_blocking = mail_led_set;
|
||||
err = devm_led_classdev_register(&client->dev, &ap->mail_led);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apanel_shutdown(struct i2c_client *client)
|
||||
{
|
||||
apanel_remove(client);
|
||||
struct apanel *ap = i2c_get_clientdata(client);
|
||||
|
||||
if (device_chip[APANEL_DEV_LED] != CHIP_NONE)
|
||||
led_set_brightness(&ap->mail_led, LED_OFF);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id apanel_id[] = {
|
||||
@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = {
|
||||
.driver = {
|
||||
.name = APANEL,
|
||||
},
|
||||
.probe = &apanel_probe,
|
||||
.remove = &apanel_remove,
|
||||
.shutdown = &apanel_shutdown,
|
||||
.probe = apanel_probe,
|
||||
.shutdown = apanel_shutdown,
|
||||
.id_table = apanel_id,
|
||||
};
|
||||
|
||||
static struct apanel apanel = {
|
||||
.keymap = {
|
||||
[0] = KEY_MAIL,
|
||||
[1] = KEY_WWW,
|
||||
[2] = KEY_PROG2,
|
||||
[3] = KEY_PROG1,
|
||||
|
||||
[8] = KEY_FORWARD,
|
||||
[9] = KEY_REWIND,
|
||||
[10] = KEY_STOPCD,
|
||||
[11] = KEY_PLAYPAUSE,
|
||||
|
||||
},
|
||||
.mail_led = {
|
||||
.name = "mail:blue",
|
||||
.brightness_set_blocking = mail_led_set,
|
||||
},
|
||||
};
|
||||
|
||||
/* NB: Only one panel on the i2c. */
|
||||
static int apanel_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct apanel *ap;
|
||||
struct input_polled_dev *ipdev;
|
||||
struct input_dev *idev;
|
||||
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
|
||||
int i, err = -ENOMEM;
|
||||
|
||||
ap = &apanel;
|
||||
|
||||
ipdev = input_allocate_polled_device();
|
||||
if (!ipdev)
|
||||
goto out1;
|
||||
|
||||
ap->ipdev = ipdev;
|
||||
ap->client = client;
|
||||
|
||||
i2c_set_clientdata(client, ap);
|
||||
|
||||
err = i2c_smbus_write_word_data(client, cmd, 0);
|
||||
if (err) {
|
||||
dev_warn(&client->dev, APANEL ": smbus write error %d\n",
|
||||
err);
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ipdev->poll = apanel_poll;
|
||||
ipdev->poll_interval = POLL_INTERVAL_DEFAULT;
|
||||
ipdev->private = ap;
|
||||
|
||||
idev = ipdev->input;
|
||||
idev->name = APANEL_NAME " buttons";
|
||||
idev->phys = "apanel/input0";
|
||||
idev->id.bustype = BUS_HOST;
|
||||
idev->dev.parent = &client->dev;
|
||||
|
||||
set_bit(EV_KEY, idev->evbit);
|
||||
|
||||
idev->keycode = ap->keymap;
|
||||
idev->keycodesize = sizeof(ap->keymap[0]);
|
||||
idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4;
|
||||
|
||||
for (i = 0; i < idev->keycodemax; i++)
|
||||
if (ap->keymap[i])
|
||||
set_bit(ap->keymap[i], idev->keybit);
|
||||
|
||||
err = input_register_polled_device(ipdev);
|
||||
if (err)
|
||||
goto out3;
|
||||
|
||||
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
|
||||
err = led_classdev_register(&client->dev, &ap->mail_led);
|
||||
if (err)
|
||||
goto out4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
out4:
|
||||
input_unregister_polled_device(ipdev);
|
||||
out3:
|
||||
input_free_polled_device(ipdev);
|
||||
out1:
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Scan the system ROM for the signature "FJKEYINF" */
|
||||
static __init const void __iomem *bios_signature(const void __iomem *bios)
|
||||
{
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
@ -123,7 +122,6 @@
|
||||
|
||||
struct bma150_data {
|
||||
struct i2c_client *client;
|
||||
struct input_polled_dev *input_polled;
|
||||
struct input_dev *input;
|
||||
u8 mode;
|
||||
};
|
||||
@ -336,13 +334,16 @@ static irqreturn_t bma150_irq_thread(int irq, void *dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void bma150_poll(struct input_polled_dev *dev)
|
||||
static void bma150_poll(struct input_dev *input)
|
||||
{
|
||||
bma150_report_xyz(dev->private);
|
||||
struct bma150_data *bma150 = input_get_drvdata(input);
|
||||
|
||||
bma150_report_xyz(bma150);
|
||||
}
|
||||
|
||||
static int bma150_open(struct bma150_data *bma150)
|
||||
static int bma150_open(struct input_dev *input)
|
||||
{
|
||||
struct bma150_data *bma150 = input_get_drvdata(input);
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get_sync(&bma150->client->dev);
|
||||
@ -362,44 +363,18 @@ static int bma150_open(struct bma150_data *bma150)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bma150_close(struct bma150_data *bma150)
|
||||
static void bma150_close(struct input_dev *input)
|
||||
{
|
||||
struct bma150_data *bma150 = input_get_drvdata(input);
|
||||
|
||||
pm_runtime_put_sync(&bma150->client->dev);
|
||||
|
||||
if (bma150->mode != BMA150_MODE_SLEEP)
|
||||
bma150_set_mode(bma150, BMA150_MODE_SLEEP);
|
||||
}
|
||||
|
||||
static int bma150_irq_open(struct input_dev *input)
|
||||
{
|
||||
struct bma150_data *bma150 = input_get_drvdata(input);
|
||||
|
||||
return bma150_open(bma150);
|
||||
}
|
||||
|
||||
static void bma150_irq_close(struct input_dev *input)
|
||||
{
|
||||
struct bma150_data *bma150 = input_get_drvdata(input);
|
||||
|
||||
bma150_close(bma150);
|
||||
}
|
||||
|
||||
static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
|
||||
{
|
||||
struct bma150_data *bma150 = ipoll_dev->private;
|
||||
|
||||
bma150_open(bma150);
|
||||
}
|
||||
|
||||
static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
|
||||
{
|
||||
struct bma150_data *bma150 = ipoll_dev->private;
|
||||
|
||||
bma150_close(bma150);
|
||||
}
|
||||
|
||||
static int bma150_initialize(struct bma150_data *bma150,
|
||||
const struct bma150_cfg *cfg)
|
||||
const struct bma150_cfg *cfg)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -439,84 +414,14 @@ static int bma150_initialize(struct bma150_data *bma150,
|
||||
return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
|
||||
}
|
||||
|
||||
static void bma150_init_input_device(struct bma150_data *bma150,
|
||||
struct input_dev *idev)
|
||||
{
|
||||
idev->name = BMA150_DRIVER;
|
||||
idev->phys = BMA150_DRIVER "/input0";
|
||||
idev->id.bustype = BUS_I2C;
|
||||
idev->dev.parent = &bma150->client->dev;
|
||||
|
||||
idev->evbit[0] = BIT_MASK(EV_ABS);
|
||||
input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
}
|
||||
|
||||
static int bma150_register_input_device(struct bma150_data *bma150)
|
||||
{
|
||||
struct input_dev *idev;
|
||||
int error;
|
||||
|
||||
idev = input_allocate_device();
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
|
||||
bma150_init_input_device(bma150, idev);
|
||||
|
||||
idev->open = bma150_irq_open;
|
||||
idev->close = bma150_irq_close;
|
||||
input_set_drvdata(idev, bma150);
|
||||
|
||||
bma150->input = idev;
|
||||
|
||||
error = input_register_device(idev);
|
||||
if (error) {
|
||||
input_free_device(idev);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma150_register_polled_device(struct bma150_data *bma150)
|
||||
{
|
||||
struct input_polled_dev *ipoll_dev;
|
||||
int error;
|
||||
|
||||
ipoll_dev = input_allocate_polled_device();
|
||||
if (!ipoll_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ipoll_dev->private = bma150;
|
||||
ipoll_dev->open = bma150_poll_open;
|
||||
ipoll_dev->close = bma150_poll_close;
|
||||
ipoll_dev->poll = bma150_poll;
|
||||
ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
|
||||
ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
|
||||
ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
|
||||
|
||||
bma150_init_input_device(bma150, ipoll_dev->input);
|
||||
|
||||
bma150->input_polled = ipoll_dev;
|
||||
bma150->input = ipoll_dev->input;
|
||||
|
||||
error = input_register_polled_device(ipoll_dev);
|
||||
if (error) {
|
||||
input_free_polled_device(ipoll_dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bma150_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct bma150_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
const struct bma150_cfg *cfg;
|
||||
struct bma150_data *bma150;
|
||||
struct input_dev *idev;
|
||||
int chip_id;
|
||||
int error;
|
||||
|
||||
@ -531,7 +436,7 @@ static int bma150_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
|
||||
bma150 = devm_kzalloc(&client->dev, sizeof(*bma150), GFP_KERNEL);
|
||||
if (!bma150)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -544,7 +449,7 @@ static int bma150_probe(struct i2c_client *client,
|
||||
dev_err(&client->dev,
|
||||
"IRQ GPIO conf. error %d, error %d\n",
|
||||
client->irq, error);
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
cfg = &pdata->cfg;
|
||||
@ -554,14 +459,42 @@ static int bma150_probe(struct i2c_client *client,
|
||||
|
||||
error = bma150_initialize(bma150, cfg);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
|
||||
idev = devm_input_allocate_device(&bma150->client->dev);
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
|
||||
input_set_drvdata(idev, bma150);
|
||||
bma150->input = idev;
|
||||
|
||||
idev->name = BMA150_DRIVER;
|
||||
idev->phys = BMA150_DRIVER "/input0";
|
||||
idev->id.bustype = BUS_I2C;
|
||||
|
||||
idev->open = bma150_open;
|
||||
idev->close = bma150_close;
|
||||
|
||||
input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
|
||||
|
||||
if (client->irq <= 0) {
|
||||
error = input_setup_polling(idev, bma150_poll);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
input_set_poll_interval(idev, BMA150_POLL_INTERVAL);
|
||||
input_set_min_poll_interval(idev, BMA150_POLL_MIN);
|
||||
input_set_max_poll_interval(idev, BMA150_POLL_MAX);
|
||||
}
|
||||
|
||||
error = input_register_device(idev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (client->irq > 0) {
|
||||
error = bma150_register_input_device(bma150);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
|
||||
error = request_threaded_irq(client->irq,
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, bma150_irq_thread,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
BMA150_DRIVER, bma150);
|
||||
@ -569,13 +502,8 @@ static int bma150_probe(struct i2c_client *client,
|
||||
dev_err(&client->dev,
|
||||
"irq request failed %d, error %d\n",
|
||||
client->irq, error);
|
||||
input_unregister_device(bma150->input);
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
error = bma150_register_polled_device(bma150);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, bma150);
|
||||
@ -583,33 +511,16 @@ static int bma150_probe(struct i2c_client *client,
|
||||
pm_runtime_enable(&client->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_mem:
|
||||
kfree(bma150);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int bma150_remove(struct i2c_client *client)
|
||||
{
|
||||
struct bma150_data *bma150 = i2c_get_clientdata(client);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
|
||||
if (client->irq > 0) {
|
||||
free_irq(client->irq, bma150);
|
||||
input_unregister_device(bma150->input);
|
||||
} else {
|
||||
input_unregister_polled_device(bma150->input_polled);
|
||||
input_free_polled_device(bma150->input_polled);
|
||||
}
|
||||
|
||||
kfree(bma150);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int bma150_suspend(struct device *dev)
|
||||
static int __maybe_unused bma150_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct bma150_data *bma150 = i2c_get_clientdata(client);
|
||||
@ -617,14 +528,13 @@ static int bma150_suspend(struct device *dev)
|
||||
return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
|
||||
}
|
||||
|
||||
static int bma150_resume(struct device *dev)
|
||||
static int __maybe_unused bma150_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct bma150_data *bma150 = i2c_get_clientdata(client);
|
||||
|
||||
return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);
|
||||
|
||||
|
@ -4,7 +4,8 @@
|
||||
*
|
||||
* Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org>
|
||||
*/
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -26,16 +27,14 @@ static const unsigned short cobalt_map[] = {
|
||||
};
|
||||
|
||||
struct buttons_dev {
|
||||
struct input_polled_dev *poll_dev;
|
||||
unsigned short keymap[ARRAY_SIZE(cobalt_map)];
|
||||
int count[ARRAY_SIZE(cobalt_map)];
|
||||
void __iomem *reg;
|
||||
};
|
||||
|
||||
static void handle_buttons(struct input_polled_dev *dev)
|
||||
static void handle_buttons(struct input_dev *input)
|
||||
{
|
||||
struct buttons_dev *bdev = dev->private;
|
||||
struct input_dev *input = dev->input;
|
||||
struct buttons_dev *bdev = input_get_drvdata(input);
|
||||
uint32_t status;
|
||||
int i;
|
||||
|
||||
@ -62,29 +61,33 @@ static void handle_buttons(struct input_polled_dev *dev)
|
||||
static int cobalt_buttons_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct buttons_dev *bdev;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct resource *res;
|
||||
int error, i;
|
||||
|
||||
bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!bdev || !poll_dev) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
|
||||
if (!bdev)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EBUSY;
|
||||
|
||||
bdev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (!bdev->reg)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap));
|
||||
|
||||
poll_dev->private = bdev;
|
||||
poll_dev->poll = handle_buttons;
|
||||
poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
input_set_drvdata(input, bdev);
|
||||
|
||||
input = poll_dev->input;
|
||||
input->name = "Cobalt buttons";
|
||||
input->phys = "cobalt/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
||||
input->keycode = bdev->keymap;
|
||||
input->keycodemax = ARRAY_SIZE(bdev->keymap);
|
||||
@ -96,39 +99,16 @@ static int cobalt_buttons_probe(struct platform_device *pdev)
|
||||
__set_bit(bdev->keymap[i], input->keybit);
|
||||
__clear_bit(KEY_RESERVED, input->keybit);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
error = -EBUSY;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
bdev->poll_dev = poll_dev;
|
||||
bdev->reg = ioremap(res->start, resource_size(res));
|
||||
dev_set_drvdata(&pdev->dev, bdev);
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_setup_polling(input, handle_buttons);
|
||||
if (error)
|
||||
goto err_iounmap;
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
|
||||
|
||||
err_iounmap:
|
||||
iounmap(bdev->reg);
|
||||
err_free_mem:
|
||||
input_free_polled_device(poll_dev);
|
||||
kfree(bdev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cobalt_buttons_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct buttons_dev *bdev = dev_get_drvdata(dev);
|
||||
|
||||
input_unregister_polled_device(bdev->poll_dev);
|
||||
input_free_polled_device(bdev->poll_dev);
|
||||
iounmap(bdev->reg);
|
||||
kfree(bdev);
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -141,7 +121,6 @@ MODULE_ALIAS("platform:Cobalt buttons");
|
||||
|
||||
static struct platform_driver cobalt_buttons_driver = {
|
||||
.probe = cobalt_buttons_probe,
|
||||
.remove = cobalt_buttons_remove,
|
||||
.driver = {
|
||||
.name = "Cobalt buttons",
|
||||
},
|
||||
|
@ -17,14 +17,12 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct gpio_decoder {
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct gpio_descs *input_gpios;
|
||||
struct device *dev;
|
||||
u32 axis;
|
||||
@ -53,15 +51,15 @@ static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gpio_decoder_poll_gpios(struct input_polled_dev *poll_dev)
|
||||
static void gpio_decoder_poll_gpios(struct input_dev *input)
|
||||
{
|
||||
struct gpio_decoder *decoder = poll_dev->private;
|
||||
struct gpio_decoder *decoder = input_get_drvdata(input);
|
||||
int state;
|
||||
|
||||
state = gpio_decoder_get_gpios_state(decoder);
|
||||
if (state >= 0 && state != decoder->last_stable) {
|
||||
input_report_abs(poll_dev->input, decoder->axis, state);
|
||||
input_sync(poll_dev->input);
|
||||
input_report_abs(input, decoder->axis, state);
|
||||
input_sync(input);
|
||||
decoder->last_stable = state;
|
||||
}
|
||||
}
|
||||
@ -70,20 +68,23 @@ static int gpio_decoder_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_decoder *decoder;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
u32 max;
|
||||
int err;
|
||||
|
||||
decoder = devm_kzalloc(dev, sizeof(struct gpio_decoder), GFP_KERNEL);
|
||||
decoder = devm_kzalloc(dev, sizeof(*decoder), GFP_KERNEL);
|
||||
if (!decoder)
|
||||
return -ENOMEM;
|
||||
|
||||
decoder->dev = dev;
|
||||
device_property_read_u32(dev, "linux,axis", &decoder->axis);
|
||||
|
||||
decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN);
|
||||
if (IS_ERR(decoder->input_gpios)) {
|
||||
dev_err(dev, "unable to acquire input gpios\n");
|
||||
return PTR_ERR(decoder->input_gpios);
|
||||
}
|
||||
|
||||
if (decoder->input_gpios->ndescs < 2) {
|
||||
dev_err(dev, "not enough gpios found\n");
|
||||
return -EINVAL;
|
||||
@ -92,22 +93,25 @@ static int gpio_decoder_probe(struct platform_device *pdev)
|
||||
if (device_property_read_u32(dev, "decoder-max-value", &max))
|
||||
max = (1U << decoder->input_gpios->ndescs) - 1;
|
||||
|
||||
decoder->dev = dev;
|
||||
poll_dev = devm_input_allocate_polled_device(decoder->dev);
|
||||
if (!poll_dev)
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
poll_dev->private = decoder;
|
||||
poll_dev->poll = gpio_decoder_poll_gpios;
|
||||
decoder->poll_dev = poll_dev;
|
||||
input_set_drvdata(input, decoder);
|
||||
|
||||
poll_dev->input->name = pdev->name;
|
||||
poll_dev->input->id.bustype = BUS_HOST;
|
||||
input_set_abs_params(poll_dev->input, decoder->axis, 0, max, 0, 0);
|
||||
input->name = pdev->name;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input_set_abs_params(input, decoder->axis, 0, max, 0, 0);
|
||||
|
||||
err = input_register_polled_device(poll_dev);
|
||||
err = input_setup_polling(input, gpio_decoder_poll_gpios);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to register polled device\n");
|
||||
dev_err(dev, "failed to set up polling\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_register_device(input);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to register input device\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -53,28 +53,10 @@ MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
#define RTC_VERSION "1.10d"
|
||||
|
||||
static DEFINE_MUTEX(hp_sdc_rtc_mutex);
|
||||
static unsigned long epoch = 2000;
|
||||
|
||||
static struct semaphore i8042tregs;
|
||||
|
||||
static hp_sdc_irqhook hp_sdc_rtc_isr;
|
||||
|
||||
static struct fasync_struct *hp_sdc_rtc_async_queue;
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
|
||||
|
||||
static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
|
||||
|
||||
static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
|
||||
static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
|
||||
|
||||
static void hp_sdc_rtc_isr (int irq, void *dev_id,
|
||||
uint8_t status, uint8_t data)
|
||||
{
|
||||
@ -283,151 +265,6 @@ static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* not used yet */
|
||||
/* Set the i8042 real-time clock */
|
||||
static int hp_sdc_rtc_set_rt (struct timeval *setto)
|
||||
{
|
||||
uint32_t tenms;
|
||||
unsigned int days;
|
||||
hp_sdc_transaction t;
|
||||
uint8_t tseq[11] = {
|
||||
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
|
||||
HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
|
||||
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
|
||||
HP_SDC_CMD_SET_RTD, 2, 0, 0
|
||||
};
|
||||
|
||||
t.endidx = 10;
|
||||
|
||||
if (0xffff < setto->tv_sec / 86400) return -1;
|
||||
days = setto->tv_sec / 86400;
|
||||
if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
|
||||
days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
|
||||
if (days > 0xffff) return -1;
|
||||
|
||||
if (0xffffff < setto->tv_sec) return -1;
|
||||
tenms = setto->tv_sec * 100;
|
||||
if (0xffffff < setto->tv_usec / 10000) return -1;
|
||||
tenms += setto->tv_usec / 10000;
|
||||
if (tenms > 0xffffff) return -1;
|
||||
|
||||
tseq[3] = (uint8_t)(tenms & 0xff);
|
||||
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
|
||||
tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
|
||||
|
||||
tseq[9] = (uint8_t)(days & 0xff);
|
||||
tseq[10] = (uint8_t)((days >> 8) & 0xff);
|
||||
|
||||
t.seq = tseq;
|
||||
|
||||
if (hp_sdc_enqueue_transaction(&t)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the i8042 fast handshake timer */
|
||||
static int hp_sdc_rtc_set_fhs (struct timeval *setto)
|
||||
{
|
||||
uint32_t tenms;
|
||||
hp_sdc_transaction t;
|
||||
uint8_t tseq[5] = {
|
||||
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
|
||||
HP_SDC_CMD_SET_FHS, 2, 0, 0
|
||||
};
|
||||
|
||||
t.endidx = 4;
|
||||
|
||||
if (0xffff < setto->tv_sec) return -1;
|
||||
tenms = setto->tv_sec * 100;
|
||||
if (0xffff < setto->tv_usec / 10000) return -1;
|
||||
tenms += setto->tv_usec / 10000;
|
||||
if (tenms > 0xffff) return -1;
|
||||
|
||||
tseq[3] = (uint8_t)(tenms & 0xff);
|
||||
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
|
||||
|
||||
t.seq = tseq;
|
||||
|
||||
if (hp_sdc_enqueue_transaction(&t)) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Set the i8042 match timer (a.k.a. alarm) */
|
||||
#define hp_sdc_rtc_set_mt (setto) \
|
||||
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
|
||||
|
||||
/* Set the i8042 delay timer */
|
||||
#define hp_sdc_rtc_set_dt (setto) \
|
||||
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
|
||||
|
||||
/* Set the i8042 cycle timer (a.k.a. periodic) */
|
||||
#define hp_sdc_rtc_set_ct (setto) \
|
||||
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
|
||||
|
||||
/* Set one of the i8042 3-byte wide timers */
|
||||
static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
|
||||
{
|
||||
uint32_t tenms;
|
||||
hp_sdc_transaction t;
|
||||
uint8_t tseq[6] = {
|
||||
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
|
||||
0, 3, 0, 0, 0
|
||||
};
|
||||
|
||||
t.endidx = 6;
|
||||
|
||||
if (0xffffff < setto->tv_sec) return -1;
|
||||
tenms = setto->tv_sec * 100;
|
||||
if (0xffffff < setto->tv_usec / 10000) return -1;
|
||||
tenms += setto->tv_usec / 10000;
|
||||
if (tenms > 0xffffff) return -1;
|
||||
|
||||
tseq[1] = setcmd;
|
||||
tseq[3] = (uint8_t)(tenms & 0xff);
|
||||
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
|
||||
tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
|
||||
|
||||
t.seq = tseq;
|
||||
|
||||
if (hp_sdc_enqueue_transaction(&t)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
ssize_t retval;
|
||||
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
|
||||
retval = put_user(68, (unsigned long __user *)buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
unsigned long l;
|
||||
|
||||
l = 0;
|
||||
if (l != 0)
|
||||
return EPOLLIN | EPOLLRDNORM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
|
||||
{
|
||||
return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
|
||||
}
|
||||
|
||||
static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
#define YN(bit) ("no")
|
||||
@ -507,182 +344,6 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
|
||||
#undef NY
|
||||
}
|
||||
|
||||
static int hp_sdc_rtc_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
#if 1
|
||||
return -EINVAL;
|
||||
#else
|
||||
|
||||
struct rtc_time wtime;
|
||||
struct timeval ttime;
|
||||
int use_wtime = 0;
|
||||
|
||||
/* This needs major work. */
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
|
||||
case RTC_AIE_ON: /* Allow alarm interrupts. */
|
||||
case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
|
||||
case RTC_PIE_ON: /* Allow periodic ints */
|
||||
case RTC_UIE_ON: /* Allow ints for RTC updates. */
|
||||
case RTC_UIE_OFF: /* Allow ints for RTC updates. */
|
||||
{
|
||||
/* We cannot mask individual user timers and we
|
||||
cannot tell them apart when they occur, so it
|
||||
would be disingenuous to succeed these IOCTLs */
|
||||
return -EINVAL;
|
||||
}
|
||||
case RTC_ALM_READ: /* Read the present alarm time */
|
||||
{
|
||||
if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
|
||||
if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
|
||||
|
||||
wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600;
|
||||
wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60;
|
||||
wtime.tm_sec = ttime.tv_sec;
|
||||
|
||||
break;
|
||||
}
|
||||
case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
|
||||
{
|
||||
return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
|
||||
}
|
||||
case RTC_IRQP_SET: /* Set periodic IRQ rate. */
|
||||
{
|
||||
/*
|
||||
* The max we can do is 100Hz.
|
||||
*/
|
||||
|
||||
if ((arg < 1) || (arg > 100)) return -EINVAL;
|
||||
ttime.tv_sec = 0;
|
||||
ttime.tv_usec = 1000000 / arg;
|
||||
if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
|
||||
hp_sdc_rtc_freq = arg;
|
||||
return 0;
|
||||
}
|
||||
case RTC_ALM_SET: /* Store a time into the alarm */
|
||||
{
|
||||
/*
|
||||
* This expects a struct hp_sdc_rtc_time. Writing 0xff means
|
||||
* "don't care" or "match all" for PC timers. The HP SDC
|
||||
* does not support that perk, but it could be emulated fairly
|
||||
* easily. Only the tm_hour, tm_min and tm_sec are used.
|
||||
* We could do it with 10ms accuracy with the HP SDC, if the
|
||||
* rtc interface left us a way to do that.
|
||||
*/
|
||||
struct hp_sdc_rtc_time alm_tm;
|
||||
|
||||
if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
|
||||
sizeof(struct hp_sdc_rtc_time)))
|
||||
return -EFAULT;
|
||||
|
||||
if (alm_tm.tm_hour > 23) return -EINVAL;
|
||||
if (alm_tm.tm_min > 59) return -EINVAL;
|
||||
if (alm_tm.tm_sec > 59) return -EINVAL;
|
||||
|
||||
ttime.sec = alm_tm.tm_hour * 3600 +
|
||||
alm_tm.tm_min * 60 + alm_tm.tm_sec;
|
||||
ttime.usec = 0;
|
||||
if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
case RTC_RD_TIME: /* Read the time/date from RTC */
|
||||
{
|
||||
if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case RTC_SET_TIME: /* Set the RTC */
|
||||
{
|
||||
struct rtc_time hp_sdc_rtc_tm;
|
||||
unsigned char mon, day, hrs, min, sec, leap_yr;
|
||||
unsigned int yrs;
|
||||
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EACCES;
|
||||
if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
|
||||
sizeof(struct rtc_time)))
|
||||
return -EFAULT;
|
||||
|
||||
yrs = hp_sdc_rtc_tm.tm_year + 1900;
|
||||
mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
|
||||
day = hp_sdc_rtc_tm.tm_mday;
|
||||
hrs = hp_sdc_rtc_tm.tm_hour;
|
||||
min = hp_sdc_rtc_tm.tm_min;
|
||||
sec = hp_sdc_rtc_tm.tm_sec;
|
||||
|
||||
if (yrs < 1970)
|
||||
return -EINVAL;
|
||||
|
||||
leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
|
||||
|
||||
if ((mon > 12) || (day == 0))
|
||||
return -EINVAL;
|
||||
if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
|
||||
return -EINVAL;
|
||||
if ((hrs >= 24) || (min >= 60) || (sec >= 60))
|
||||
return -EINVAL;
|
||||
|
||||
if ((yrs -= eH) > 255) /* They are unsigned */
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
case RTC_EPOCH_READ: /* Read the epoch. */
|
||||
{
|
||||
return put_user (epoch, (unsigned long *)arg);
|
||||
}
|
||||
case RTC_EPOCH_SET: /* Set the epoch. */
|
||||
{
|
||||
/*
|
||||
* There were no RTC clocks before 1900.
|
||||
*/
|
||||
if (arg < 1900)
|
||||
return -EINVAL;
|
||||
if (!capable(CAP_SYS_TIME))
|
||||
return -EACCES;
|
||||
|
||||
epoch = arg;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&hp_sdc_rtc_mutex);
|
||||
ret = hp_sdc_rtc_ioctl(file, cmd, arg);
|
||||
mutex_unlock(&hp_sdc_rtc_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations hp_sdc_rtc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = hp_sdc_rtc_read,
|
||||
.poll = hp_sdc_rtc_poll,
|
||||
.unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl,
|
||||
.open = hp_sdc_rtc_open,
|
||||
.fasync = hp_sdc_rtc_fasync,
|
||||
};
|
||||
|
||||
static struct miscdevice hp_sdc_rtc_dev = {
|
||||
.minor = RTC_MINOR,
|
||||
.name = "rtc_HIL",
|
||||
.fops = &hp_sdc_rtc_fops
|
||||
};
|
||||
|
||||
static int __init hp_sdc_rtc_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -696,8 +357,6 @@ static int __init hp_sdc_rtc_init(void)
|
||||
|
||||
if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
|
||||
return ret;
|
||||
if (misc_register(&hp_sdc_rtc_dev) != 0)
|
||||
printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
|
||||
|
||||
proc_create_single("driver/rtc", 0, NULL, hp_sdc_rtc_proc_show);
|
||||
|
||||
@ -710,7 +369,6 @@ static int __init hp_sdc_rtc_init(void)
|
||||
static void __exit hp_sdc_rtc_exit(void)
|
||||
{
|
||||
remove_proc_entry ("driver/rtc", NULL);
|
||||
misc_deregister(&hp_sdc_rtc_dev);
|
||||
hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
|
||||
printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input/kxtj9.h>
|
||||
#include <linux/input-polldev.h>
|
||||
|
||||
#define NAME "kxtj9"
|
||||
#define G_MAX 8000
|
||||
@ -71,9 +70,6 @@ struct kxtj9_data {
|
||||
struct i2c_client *client;
|
||||
struct kxtj9_platform_data pdata;
|
||||
struct input_dev *input_dev;
|
||||
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
|
||||
struct input_polled_dev *poll_dev;
|
||||
#endif
|
||||
unsigned int last_poll_interval;
|
||||
u8 shift;
|
||||
u8 ctrl_reg1;
|
||||
@ -282,50 +278,6 @@ static void kxtj9_input_close(struct input_dev *dev)
|
||||
kxtj9_disable(tj9);
|
||||
}
|
||||
|
||||
static void kxtj9_init_input_device(struct kxtj9_data *tj9,
|
||||
struct input_dev *input_dev)
|
||||
{
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
|
||||
input_dev->name = "kxtj9_accel";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = &tj9->client->dev;
|
||||
}
|
||||
|
||||
static int kxtj9_setup_input_device(struct kxtj9_data *tj9)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(&tj9->client->dev, "input device allocate failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tj9->input_dev = input_dev;
|
||||
|
||||
input_dev->open = kxtj9_input_open;
|
||||
input_dev->close = kxtj9_input_close;
|
||||
input_set_drvdata(input_dev, tj9);
|
||||
|
||||
kxtj9_init_input_device(tj9, input_dev);
|
||||
|
||||
err = input_register_device(tj9->input_dev);
|
||||
if (err) {
|
||||
dev_err(&tj9->client->dev,
|
||||
"unable to register input polled device %s: %d\n",
|
||||
tj9->input_dev->name, err);
|
||||
input_free_device(tj9->input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When IRQ mode is selected, we need to provide an interface to allow the user
|
||||
* to change the output data rate of the part. For consistency, we are using
|
||||
@ -391,12 +343,10 @@ static struct attribute_group kxtj9_attribute_group = {
|
||||
.attrs = kxtj9_attributes
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
|
||||
static void kxtj9_poll(struct input_polled_dev *dev)
|
||||
static void kxtj9_poll(struct input_dev *input)
|
||||
{
|
||||
struct kxtj9_data *tj9 = dev->private;
|
||||
unsigned int poll_interval = dev->poll_interval;
|
||||
struct kxtj9_data *tj9 = input_get_drvdata(input);
|
||||
unsigned int poll_interval = input_get_poll_interval(input);
|
||||
|
||||
kxtj9_report_acceleration_data(tj9);
|
||||
|
||||
@ -406,72 +356,14 @@ static void kxtj9_poll(struct input_polled_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void kxtj9_polled_input_open(struct input_polled_dev *dev)
|
||||
static void kxtj9_platform_exit(void *data)
|
||||
{
|
||||
struct kxtj9_data *tj9 = dev->private;
|
||||
struct kxtj9_data *tj9 = data;
|
||||
|
||||
kxtj9_enable(tj9);
|
||||
if (tj9->pdata.exit)
|
||||
tj9->pdata.exit();
|
||||
}
|
||||
|
||||
static void kxtj9_polled_input_close(struct input_polled_dev *dev)
|
||||
{
|
||||
struct kxtj9_data *tj9 = dev->private;
|
||||
|
||||
kxtj9_disable(tj9);
|
||||
}
|
||||
|
||||
static int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
|
||||
{
|
||||
int err;
|
||||
struct input_polled_dev *poll_dev;
|
||||
poll_dev = input_allocate_polled_device();
|
||||
|
||||
if (!poll_dev) {
|
||||
dev_err(&tj9->client->dev,
|
||||
"Failed to allocate polled device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tj9->poll_dev = poll_dev;
|
||||
tj9->input_dev = poll_dev->input;
|
||||
|
||||
poll_dev->private = tj9;
|
||||
poll_dev->poll = kxtj9_poll;
|
||||
poll_dev->open = kxtj9_polled_input_open;
|
||||
poll_dev->close = kxtj9_polled_input_close;
|
||||
|
||||
kxtj9_init_input_device(tj9, poll_dev->input);
|
||||
|
||||
err = input_register_polled_device(poll_dev);
|
||||
if (err) {
|
||||
dev_err(&tj9->client->dev,
|
||||
"Unable to register polled device, err=%d\n", err);
|
||||
input_free_polled_device(poll_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
|
||||
{
|
||||
input_unregister_polled_device(tj9->poll_dev);
|
||||
input_free_polled_device(tj9->poll_dev);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int kxtj9_verify(struct kxtj9_data *tj9)
|
||||
{
|
||||
int retval;
|
||||
@ -494,11 +386,12 @@ out:
|
||||
}
|
||||
|
||||
static int kxtj9_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct kxtj9_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
struct kxtj9_data *tj9;
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
@ -512,7 +405,7 @@ static int kxtj9_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
|
||||
tj9 = devm_kzalloc(&client->dev, sizeof(*tj9), GFP_KERNEL);
|
||||
if (!tj9) {
|
||||
dev_err(&client->dev,
|
||||
"failed to allocate memory for module data\n");
|
||||
@ -525,13 +418,17 @@ static int kxtj9_probe(struct i2c_client *client,
|
||||
if (pdata->init) {
|
||||
err = pdata->init();
|
||||
if (err < 0)
|
||||
goto err_free_mem;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = devm_add_action_or_reset(&client->dev, kxtj9_platform_exit, tj9);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = kxtj9_verify(tj9);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "device not recognized\n");
|
||||
goto err_pdata_exit;
|
||||
return err;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, tj9);
|
||||
@ -539,66 +436,62 @@ static int kxtj9_probe(struct i2c_client *client,
|
||||
tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
|
||||
tj9->last_poll_interval = tj9->pdata.init_interval;
|
||||
|
||||
input_dev = devm_input_allocate_device(&client->dev);
|
||||
if (!input_dev) {
|
||||
dev_err(&client->dev, "input device allocate failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
input_set_drvdata(input_dev, tj9);
|
||||
tj9->input_dev = input_dev;
|
||||
|
||||
input_dev->name = "kxtj9_accel";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
|
||||
input_dev->open = kxtj9_input_open;
|
||||
input_dev->close = kxtj9_input_close;
|
||||
|
||||
input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
|
||||
|
||||
if (client->irq <= 0) {
|
||||
err = input_setup_polling(input_dev, kxtj9_poll);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
dev_err(&client->dev,
|
||||
"unable to register input polled device %s: %d\n",
|
||||
input_dev->name, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (client->irq) {
|
||||
/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
|
||||
tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
|
||||
tj9->ctrl_reg1 |= DRDYE;
|
||||
|
||||
err = kxtj9_setup_input_device(tj9);
|
||||
if (err)
|
||||
goto err_pdata_exit;
|
||||
|
||||
err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"kxtj9-irq", tj9);
|
||||
err = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, kxtj9_isr,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_ONESHOT,
|
||||
"kxtj9-irq", tj9);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "request irq failed: %d\n", err);
|
||||
goto err_destroy_input;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
|
||||
err = devm_device_add_group(&client->dev,
|
||||
&kxtj9_attribute_group);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "sysfs create failed: %d\n", err);
|
||||
goto err_free_irq;
|
||||
return err;
|
||||
}
|
||||
|
||||
} else {
|
||||
err = kxtj9_setup_polled_device(tj9);
|
||||
if (err)
|
||||
goto err_pdata_exit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(client->irq, tj9);
|
||||
err_destroy_input:
|
||||
input_unregister_device(tj9->input_dev);
|
||||
err_pdata_exit:
|
||||
if (tj9->pdata.exit)
|
||||
tj9->pdata.exit();
|
||||
err_free_mem:
|
||||
kfree(tj9);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int kxtj9_remove(struct i2c_client *client)
|
||||
{
|
||||
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
|
||||
|
||||
if (client->irq) {
|
||||
sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group);
|
||||
free_irq(client->irq, tj9);
|
||||
input_unregister_device(tj9->input_dev);
|
||||
} else {
|
||||
kxtj9_teardown_polled_device(tj9);
|
||||
}
|
||||
|
||||
if (tj9->pdata.exit)
|
||||
tj9->pdata.exit();
|
||||
|
||||
kfree(tj9);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -647,7 +540,6 @@ static struct i2c_driver kxtj9_driver = {
|
||||
.pm = &kxtj9_pm_ops,
|
||||
},
|
||||
.probe = kxtj9_probe,
|
||||
.remove = kxtj9_remove,
|
||||
.id_table = kxtj9_id,
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#define MMA8450_DRV_NAME "mma8450"
|
||||
@ -39,15 +39,8 @@
|
||||
#define MMA8450_CTRL_REG1 0x38
|
||||
#define MMA8450_CTRL_REG2 0x39
|
||||
|
||||
/* mma8450 status */
|
||||
struct mma8450 {
|
||||
struct i2c_client *client;
|
||||
struct input_polled_dev *idev;
|
||||
};
|
||||
|
||||
static int mma8450_read(struct mma8450 *m, unsigned off)
|
||||
static int mma8450_read(struct i2c_client *c, unsigned int off)
|
||||
{
|
||||
struct i2c_client *c = m->client;
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(c, off);
|
||||
@ -59,9 +52,8 @@ static int mma8450_read(struct mma8450 *m, unsigned off)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
|
||||
static int mma8450_write(struct i2c_client *c, unsigned int off, u8 v)
|
||||
{
|
||||
struct i2c_client *c = m->client;
|
||||
int error;
|
||||
|
||||
error = i2c_smbus_write_byte_data(c, off, v);
|
||||
@ -75,10 +67,9 @@ static int mma8450_write(struct mma8450 *m, unsigned off, u8 v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mma8450_read_block(struct mma8450 *m, unsigned off,
|
||||
static int mma8450_read_block(struct i2c_client *c, unsigned int off,
|
||||
u8 *buf, size_t size)
|
||||
{
|
||||
struct i2c_client *c = m->client;
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(c, off, size, buf);
|
||||
@ -92,21 +83,21 @@ static int mma8450_read_block(struct mma8450 *m, unsigned off,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mma8450_poll(struct input_polled_dev *dev)
|
||||
static void mma8450_poll(struct input_dev *input)
|
||||
{
|
||||
struct mma8450 *m = dev->private;
|
||||
struct i2c_client *c = input_get_drvdata(input);
|
||||
int x, y, z;
|
||||
int ret;
|
||||
u8 buf[6];
|
||||
|
||||
ret = mma8450_read(m, MMA8450_STATUS);
|
||||
ret = mma8450_read(c, MMA8450_STATUS);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (!(ret & MMA8450_STATUS_ZXYDR))
|
||||
return;
|
||||
|
||||
ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf));
|
||||
ret = mma8450_read_block(c, MMA8450_OUT_X_LSB, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
@ -114,41 +105,42 @@ static void mma8450_poll(struct input_polled_dev *dev)
|
||||
y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
|
||||
z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf);
|
||||
|
||||
input_report_abs(dev->input, ABS_X, x);
|
||||
input_report_abs(dev->input, ABS_Y, y);
|
||||
input_report_abs(dev->input, ABS_Z, z);
|
||||
input_sync(dev->input);
|
||||
input_report_abs(input, ABS_X, x);
|
||||
input_report_abs(input, ABS_Y, y);
|
||||
input_report_abs(input, ABS_Z, z);
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
/* Initialize the MMA8450 chip */
|
||||
static void mma8450_open(struct input_polled_dev *dev)
|
||||
static int mma8450_open(struct input_dev *input)
|
||||
{
|
||||
struct mma8450 *m = dev->private;
|
||||
struct i2c_client *c = input_get_drvdata(input);
|
||||
int err;
|
||||
|
||||
/* enable all events from X/Y/Z, no FIFO */
|
||||
err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07);
|
||||
err = mma8450_write(c, MMA8450_XYZ_DATA_CFG, 0x07);
|
||||
if (err)
|
||||
return;
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Sleep mode poll rate - 50Hz
|
||||
* System output data rate - 400Hz
|
||||
* Full scale selection - Active, +/- 2G
|
||||
*/
|
||||
err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01);
|
||||
if (err < 0)
|
||||
return;
|
||||
err = mma8450_write(c, MMA8450_CTRL_REG1, 0x01);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
msleep(MODE_CHANGE_DELAY_MS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mma8450_close(struct input_polled_dev *dev)
|
||||
static void mma8450_close(struct input_dev *input)
|
||||
{
|
||||
struct mma8450 *m = dev->private;
|
||||
struct i2c_client *c = input_get_drvdata(input);
|
||||
|
||||
mma8450_write(m, MMA8450_CTRL_REG1, 0x00);
|
||||
mma8450_write(m, MMA8450_CTRL_REG2, 0x01);
|
||||
mma8450_write(c, MMA8450_CTRL_REG1, 0x00);
|
||||
mma8450_write(c, MMA8450_CTRL_REG2, 0x01);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -157,38 +149,37 @@ static void mma8450_close(struct input_polled_dev *dev)
|
||||
static int mma8450_probe(struct i2c_client *c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct input_polled_dev *idev;
|
||||
struct mma8450 *m;
|
||||
struct input_dev *input;
|
||||
int err;
|
||||
|
||||
m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL);
|
||||
if (!m)
|
||||
input = devm_input_allocate_device(&c->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
idev = devm_input_allocate_polled_device(&c->dev);
|
||||
if (!idev)
|
||||
return -ENOMEM;
|
||||
input_set_drvdata(input, c);
|
||||
|
||||
m->client = c;
|
||||
m->idev = idev;
|
||||
input->name = MMA8450_DRV_NAME;
|
||||
input->id.bustype = BUS_I2C;
|
||||
|
||||
idev->private = m;
|
||||
idev->input->name = MMA8450_DRV_NAME;
|
||||
idev->input->id.bustype = BUS_I2C;
|
||||
idev->poll = mma8450_poll;
|
||||
idev->poll_interval = POLL_INTERVAL;
|
||||
idev->poll_interval_max = POLL_INTERVAL_MAX;
|
||||
idev->open = mma8450_open;
|
||||
idev->close = mma8450_close;
|
||||
input->open = mma8450_open;
|
||||
input->close = mma8450_close;
|
||||
|
||||
__set_bit(EV_ABS, idev->input->evbit);
|
||||
input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32);
|
||||
input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32);
|
||||
input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
|
||||
input_set_abs_params(input, ABS_X, -2048, 2047, 32, 32);
|
||||
input_set_abs_params(input, ABS_Y, -2048, 2047, 32, 32);
|
||||
input_set_abs_params(input, ABS_Z, -2048, 2047, 32, 32);
|
||||
|
||||
err = input_register_polled_device(idev);
|
||||
err = input_setup_polling(input, mma8450_poll);
|
||||
if (err) {
|
||||
dev_err(&c->dev, "failed to register polled input device\n");
|
||||
dev_err(&c->dev, "failed to set up polling\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input, POLL_INTERVAL);
|
||||
input_set_max_poll_interval(input, POLL_INTERVAL_MAX);
|
||||
|
||||
err = input_register_device(input);
|
||||
if (err) {
|
||||
dev_err(&c->dev, "failed to register input device\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org>
|
||||
*/
|
||||
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
@ -46,56 +46,42 @@ static bool rb532_button_pressed(void)
|
||||
return !val;
|
||||
}
|
||||
|
||||
static void rb532_button_poll(struct input_polled_dev *poll_dev)
|
||||
static void rb532_button_poll(struct input_dev *input)
|
||||
{
|
||||
input_report_key(poll_dev->input, RB532_BTN_KSYM,
|
||||
rb532_button_pressed());
|
||||
input_sync(poll_dev->input);
|
||||
input_report_key(input, RB532_BTN_KSYM, rb532_button_pressed());
|
||||
input_sync(input);
|
||||
}
|
||||
|
||||
static int rb532_button_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!poll_dev)
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
poll_dev->poll = rb532_button_poll;
|
||||
poll_dev->poll_interval = RB532_BTN_RATE;
|
||||
input->name = "rb532 button";
|
||||
input->phys = "rb532/button0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
|
||||
poll_dev->input->name = "rb532 button";
|
||||
poll_dev->input->phys = "rb532/button0";
|
||||
poll_dev->input->id.bustype = BUS_HOST;
|
||||
poll_dev->input->dev.parent = &pdev->dev;
|
||||
input_set_capability(input, EV_KEY, RB532_BTN_KSYM);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, poll_dev);
|
||||
|
||||
input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM);
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
if (error) {
|
||||
input_free_polled_device(poll_dev);
|
||||
error = input_setup_polling(input, rb532_button_poll);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
input_set_poll_interval(input, RB532_BTN_RATE);
|
||||
|
||||
static int rb532_button_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
input_unregister_polled_device(poll_dev);
|
||||
input_free_polled_device(poll_dev);
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rb532_button_driver = {
|
||||
.probe = rb532_button_probe,
|
||||
.remove = rb532_button_remove,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
|
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
||||
*/
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -45,15 +45,13 @@ static const unsigned short sgi_map[] = {
|
||||
};
|
||||
|
||||
struct buttons_dev {
|
||||
struct input_polled_dev *poll_dev;
|
||||
unsigned short keymap[ARRAY_SIZE(sgi_map)];
|
||||
int count[ARRAY_SIZE(sgi_map)];
|
||||
};
|
||||
|
||||
static void handle_buttons(struct input_polled_dev *dev)
|
||||
static void handle_buttons(struct input_dev *input)
|
||||
{
|
||||
struct buttons_dev *bdev = dev->private;
|
||||
struct input_dev *input = dev->input;
|
||||
struct buttons_dev *bdev = input_get_drvdata(input);
|
||||
u8 status;
|
||||
int i;
|
||||
|
||||
@ -80,28 +78,24 @@ static void handle_buttons(struct input_polled_dev *dev)
|
||||
static int sgi_buttons_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct buttons_dev *bdev;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
int error, i;
|
||||
|
||||
bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL);
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!bdev || !poll_dev) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
|
||||
if (!bdev)
|
||||
return -ENOMEM;
|
||||
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
|
||||
|
||||
poll_dev->private = bdev;
|
||||
poll_dev->poll = handle_buttons;
|
||||
poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
|
||||
input_set_drvdata(input, bdev);
|
||||
|
||||
input = poll_dev->input;
|
||||
input->name = "SGI buttons";
|
||||
input->phys = "sgi/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
||||
input->keycode = bdev->keymap;
|
||||
input->keycodemax = ARRAY_SIZE(bdev->keymap);
|
||||
@ -113,35 +107,21 @@ static int sgi_buttons_probe(struct platform_device *pdev)
|
||||
__set_bit(bdev->keymap[i], input->keybit);
|
||||
__clear_bit(KEY_RESERVED, input->keybit);
|
||||
|
||||
bdev->poll_dev = poll_dev;
|
||||
platform_set_drvdata(pdev, bdev);
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_setup_polling(input, handle_buttons);
|
||||
if (error)
|
||||
goto err_free_mem;
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
|
||||
|
||||
err_free_mem:
|
||||
input_free_polled_device(poll_dev);
|
||||
kfree(bdev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int sgi_buttons_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct buttons_dev *bdev = platform_get_drvdata(pdev);
|
||||
|
||||
input_unregister_polled_device(bdev->poll_dev);
|
||||
input_free_polled_device(bdev->poll_dev);
|
||||
kfree(bdev);
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sgi_buttons_driver = {
|
||||
.probe = sgi_buttons_probe,
|
||||
.remove = sgi_buttons_remove,
|
||||
.driver = {
|
||||
.name = "sgibtns",
|
||||
},
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
@ -1030,7 +1030,7 @@ static int __init select_keymap(void)
|
||||
|
||||
/* Input layer interface */
|
||||
|
||||
static struct input_polled_dev *wistron_idev;
|
||||
static struct input_dev *wistron_idev;
|
||||
static unsigned long jiffies_last_press;
|
||||
static bool wifi_enabled;
|
||||
static bool bluetooth_enabled;
|
||||
@ -1114,7 +1114,7 @@ static inline void wistron_led_resume(void)
|
||||
static void handle_key(u8 code)
|
||||
{
|
||||
const struct key_entry *key =
|
||||
sparse_keymap_entry_from_scancode(wistron_idev->input, code);
|
||||
sparse_keymap_entry_from_scancode(wistron_idev, code);
|
||||
|
||||
if (key) {
|
||||
switch (key->type) {
|
||||
@ -1133,14 +1133,14 @@ static void handle_key(u8 code)
|
||||
break;
|
||||
|
||||
default:
|
||||
sparse_keymap_report_entry(wistron_idev->input,
|
||||
key, 1, true);
|
||||
sparse_keymap_report_entry(wistron_idev, key, 1, true);
|
||||
break;
|
||||
}
|
||||
jiffies_last_press = jiffies;
|
||||
} else
|
||||
} else {
|
||||
printk(KERN_NOTICE
|
||||
"wistron_btns: Unknown key code %02X\n", code);
|
||||
}
|
||||
}
|
||||
|
||||
static void poll_bios(bool discard)
|
||||
@ -1158,21 +1158,23 @@ static void poll_bios(bool discard)
|
||||
}
|
||||
}
|
||||
|
||||
static void wistron_flush(struct input_polled_dev *dev)
|
||||
static int wistron_flush(struct input_dev *dev)
|
||||
{
|
||||
/* Flush stale event queue */
|
||||
poll_bios(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wistron_poll(struct input_polled_dev *dev)
|
||||
static void wistron_poll(struct input_dev *dev)
|
||||
{
|
||||
poll_bios(false);
|
||||
|
||||
/* Increase poll frequency if user is currently pressing keys (< 2s ago) */
|
||||
if (time_before(jiffies, jiffies_last_press + 2 * HZ))
|
||||
dev->poll_interval = POLL_INTERVAL_BURST;
|
||||
input_set_poll_interval(dev, POLL_INTERVAL_BURST);
|
||||
else
|
||||
dev->poll_interval = POLL_INTERVAL_DEFAULT;
|
||||
input_set_poll_interval(dev, POLL_INTERVAL_DEFAULT);
|
||||
}
|
||||
|
||||
static int wistron_setup_keymap(struct input_dev *dev,
|
||||
@ -1208,35 +1210,37 @@ static int wistron_setup_keymap(struct input_dev *dev,
|
||||
|
||||
static int setup_input_dev(void)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
wistron_idev = input_allocate_polled_device();
|
||||
wistron_idev = input_allocate_device();
|
||||
if (!wistron_idev)
|
||||
return -ENOMEM;
|
||||
|
||||
wistron_idev->name = "Wistron laptop buttons";
|
||||
wistron_idev->phys = "wistron/input0";
|
||||
wistron_idev->id.bustype = BUS_HOST;
|
||||
wistron_idev->dev.parent = &wistron_device->dev;
|
||||
|
||||
wistron_idev->open = wistron_flush;
|
||||
wistron_idev->poll = wistron_poll;
|
||||
wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
|
||||
|
||||
input_dev = wistron_idev->input;
|
||||
input_dev->name = "Wistron laptop buttons";
|
||||
input_dev->phys = "wistron/input0";
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
input_dev->dev.parent = &wistron_device->dev;
|
||||
|
||||
error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
|
||||
error = sparse_keymap_setup(wistron_idev, keymap, wistron_setup_keymap);
|
||||
if (error)
|
||||
goto err_free_dev;
|
||||
|
||||
error = input_register_polled_device(wistron_idev);
|
||||
error = input_setup_polling(wistron_idev, wistron_poll);
|
||||
if (error)
|
||||
goto err_free_dev;
|
||||
|
||||
input_set_poll_interval(wistron_idev, POLL_INTERVAL_DEFAULT);
|
||||
|
||||
error = input_register_device(wistron_idev);
|
||||
if (error)
|
||||
goto err_free_dev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_dev:
|
||||
input_free_polled_device(wistron_idev);
|
||||
input_free_device(wistron_idev);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1285,8 +1289,7 @@ static int wistron_probe(struct platform_device *dev)
|
||||
static int wistron_remove(struct platform_device *dev)
|
||||
{
|
||||
wistron_led_remove();
|
||||
input_unregister_polled_device(wistron_idev);
|
||||
input_free_polled_device(wistron_idev);
|
||||
input_unregister_device(wistron_idev);
|
||||
bios_detach();
|
||||
|
||||
return 0;
|
||||
|
@ -92,14 +92,14 @@ config MOUSE_PS2_SYNAPTICS_SMBUS
|
||||
If unsure, say Y.
|
||||
|
||||
config MOUSE_PS2_CYPRESS
|
||||
bool "Cypress PS/2 mouse protocol extension" if EXPERT
|
||||
default y
|
||||
depends on MOUSE_PS2
|
||||
help
|
||||
Say Y here if you have a Cypress PS/2 Trackpad connected to
|
||||
your system.
|
||||
bool "Cypress PS/2 mouse protocol extension" if EXPERT
|
||||
default y
|
||||
depends on MOUSE_PS2
|
||||
help
|
||||
Say Y here if you have a Cypress PS/2 Trackpad connected to
|
||||
your system.
|
||||
|
||||
If unsure, say Y.
|
||||
If unsure, say Y.
|
||||
|
||||
config MOUSE_PS2_LIFEBOOK
|
||||
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
|
||||
@ -381,7 +381,6 @@ config MOUSE_VSXXXAA
|
||||
config MOUSE_GPIO
|
||||
tristate "GPIO mouse"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
This driver simulates a mouse on GPIO lines of various CPUs (and some
|
||||
other chips).
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/of.h>
|
||||
@ -43,10 +43,9 @@ struct gpio_mouse {
|
||||
* Timer function which is run every scan_ms ms when the device is opened.
|
||||
* The dev input variable is set to the the input_dev pointer.
|
||||
*/
|
||||
static void gpio_mouse_scan(struct input_polled_dev *dev)
|
||||
static void gpio_mouse_scan(struct input_dev *input)
|
||||
{
|
||||
struct gpio_mouse *gpio = dev->private;
|
||||
struct input_dev *input = dev->input;
|
||||
struct gpio_mouse *gpio = input_get_drvdata(input);
|
||||
int x, y;
|
||||
|
||||
if (gpio->bleft)
|
||||
@ -71,18 +70,17 @@ static int gpio_mouse_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_mouse *gmouse;
|
||||
struct input_polled_dev *input_poll;
|
||||
struct input_dev *input;
|
||||
int ret;
|
||||
int error;
|
||||
|
||||
gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
|
||||
if (!gmouse)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Assign some default scanning time */
|
||||
ret = device_property_read_u32(dev, "scan-interval-ms",
|
||||
&gmouse->scan_ms);
|
||||
if (ret || gmouse->scan_ms == 0) {
|
||||
error = device_property_read_u32(dev, "scan-interval-ms",
|
||||
&gmouse->scan_ms);
|
||||
if (error || gmouse->scan_ms == 0) {
|
||||
dev_warn(dev, "invalid scan time, set to 50 ms\n");
|
||||
gmouse->scan_ms = 50;
|
||||
}
|
||||
@ -112,23 +110,14 @@ static int gpio_mouse_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(gmouse->bright))
|
||||
return PTR_ERR(gmouse->bright);
|
||||
|
||||
input_poll = devm_input_allocate_polled_device(dev);
|
||||
if (!input_poll) {
|
||||
dev_err(dev, "not enough memory for input device\n");
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, input_poll);
|
||||
|
||||
/* set input-polldev handlers */
|
||||
input_poll->private = gmouse;
|
||||
input_poll->poll = gpio_mouse_scan;
|
||||
input_poll->poll_interval = gmouse->scan_ms;
|
||||
|
||||
input = input_poll->input;
|
||||
input->name = pdev->name;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->dev.parent = &pdev->dev;
|
||||
|
||||
input_set_drvdata(input, gmouse);
|
||||
|
||||
input_set_capability(input, EV_REL, REL_X);
|
||||
input_set_capability(input, EV_REL, REL_Y);
|
||||
@ -139,10 +128,16 @@ static int gpio_mouse_probe(struct platform_device *pdev)
|
||||
if (gmouse->bright)
|
||||
input_set_capability(input, EV_KEY, BTN_RIGHT);
|
||||
|
||||
ret = input_register_polled_device(input_poll);
|
||||
if (ret) {
|
||||
error = input_setup_polling(input, gpio_mouse_scan);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
input_set_poll_interval(input, gmouse->scan_ms);
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(dev, "could not register input device\n");
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",
|
||||
|
@ -172,6 +172,7 @@ static const char * const smbus_pnp_ids[] = {
|
||||
"LEN0071", /* T480 */
|
||||
"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
|
||||
"LEN0073", /* X1 Carbon G5 (Elantech) */
|
||||
"LEN0091", /* X1 Carbon 6 */
|
||||
"LEN0092", /* X1 Carbon 6 */
|
||||
"LEN0093", /* T480 */
|
||||
"LEN0096", /* X280 */
|
||||
|
@ -81,11 +81,6 @@ static const char * const rmi_f54_report_type_names[] = {
|
||||
= "Full Raw Capacitance RX Offset Removed",
|
||||
};
|
||||
|
||||
struct rmi_f54_reports {
|
||||
int start;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct f54_data {
|
||||
struct rmi_function *fn;
|
||||
|
||||
@ -98,7 +93,6 @@ struct f54_data {
|
||||
enum rmi_f54_report_type report_type;
|
||||
u8 *report_data;
|
||||
int report_size;
|
||||
struct rmi_f54_reports standard_report[2];
|
||||
|
||||
bool is_busy;
|
||||
struct mutex status_mutex;
|
||||
@ -116,6 +110,7 @@ struct f54_data {
|
||||
struct video_device vdev;
|
||||
struct vb2_queue queue;
|
||||
struct mutex lock;
|
||||
u32 sequence;
|
||||
int input;
|
||||
enum rmi_f54_report_type inputs[F54_MAX_REPORT_TYPE];
|
||||
};
|
||||
@ -290,6 +285,7 @@ static int rmi_f54_queue_setup(struct vb2_queue *q, unsigned int *nbuffers,
|
||||
|
||||
static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct f54_data *f54 = vb2_get_drv_priv(vb->vb2_queue);
|
||||
u16 *ptr;
|
||||
enum vb2_buffer_state state;
|
||||
@ -298,6 +294,7 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
|
||||
|
||||
mutex_lock(&f54->status_mutex);
|
||||
|
||||
vb2_set_plane_payload(vb, 0, 0);
|
||||
reptype = rmi_f54_get_reptype(f54, f54->input);
|
||||
if (reptype == F54_REPORT_NONE) {
|
||||
state = VB2_BUF_STATE_ERROR;
|
||||
@ -344,14 +341,25 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
|
||||
data_done:
|
||||
mutex_unlock(&f54->data_mutex);
|
||||
done:
|
||||
vb->timestamp = ktime_get_ns();
|
||||
vbuf->field = V4L2_FIELD_NONE;
|
||||
vbuf->sequence = f54->sequence++;
|
||||
vb2_buffer_done(vb, state);
|
||||
mutex_unlock(&f54->status_mutex);
|
||||
}
|
||||
|
||||
static void rmi_f54_stop_streaming(struct vb2_queue *q)
|
||||
{
|
||||
struct f54_data *f54 = vb2_get_drv_priv(q);
|
||||
|
||||
f54->sequence = 0;
|
||||
}
|
||||
|
||||
/* V4L2 structures */
|
||||
static const struct vb2_ops rmi_f54_queue_ops = {
|
||||
.queue_setup = rmi_f54_queue_setup,
|
||||
.buf_queue = rmi_f54_buffer_queue,
|
||||
.stop_streaming = rmi_f54_stop_streaming,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
.wait_finish = vb2_ops_wait_finish,
|
||||
};
|
||||
@ -363,7 +371,6 @@ static const struct vb2_queue rmi_f54_queue = {
|
||||
.ops = &rmi_f54_queue_ops,
|
||||
.mem_ops = &vb2_vmalloc_memops,
|
||||
.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
|
||||
.min_buffers_needed = 1,
|
||||
};
|
||||
|
||||
static int rmi_f54_vidioc_querycap(struct file *file, void *priv,
|
||||
@ -516,13 +523,10 @@ static void rmi_f54_work(struct work_struct *work)
|
||||
struct f54_data *f54 = container_of(work, struct f54_data, work.work);
|
||||
struct rmi_function *fn = f54->fn;
|
||||
u8 fifo[2];
|
||||
struct rmi_f54_reports *report;
|
||||
int report_size;
|
||||
u8 command;
|
||||
u8 *data;
|
||||
int error;
|
||||
|
||||
data = f54->report_data;
|
||||
report_size = rmi_f54_get_report_size(f54);
|
||||
if (report_size == 0) {
|
||||
dev_err(&fn->dev, "Bad report size, report type=%d\n",
|
||||
@ -530,8 +534,6 @@ static void rmi_f54_work(struct work_struct *work)
|
||||
error = -EINVAL;
|
||||
goto error; /* retry won't help */
|
||||
}
|
||||
f54->standard_report[0].size = report_size;
|
||||
report = f54->standard_report;
|
||||
|
||||
mutex_lock(&f54->data_mutex);
|
||||
|
||||
@ -556,28 +558,23 @@ static void rmi_f54_work(struct work_struct *work)
|
||||
|
||||
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n");
|
||||
|
||||
report_size = 0;
|
||||
for (; report->size; report++) {
|
||||
fifo[0] = report->start & 0xff;
|
||||
fifo[1] = (report->start >> 8) & 0xff;
|
||||
error = rmi_write_block(fn->rmi_dev,
|
||||
fn->fd.data_base_addr + F54_FIFO_OFFSET,
|
||||
fifo, sizeof(fifo));
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "Failed to set fifo start offset\n");
|
||||
goto abort;
|
||||
}
|
||||
fifo[0] = 0;
|
||||
fifo[1] = 0;
|
||||
error = rmi_write_block(fn->rmi_dev,
|
||||
fn->fd.data_base_addr + F54_FIFO_OFFSET,
|
||||
fifo, sizeof(fifo));
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "Failed to set fifo start offset\n");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
|
||||
F54_REPORT_DATA_OFFSET, data,
|
||||
report->size);
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
|
||||
__func__, report->size, error);
|
||||
goto abort;
|
||||
}
|
||||
data += report->size;
|
||||
report_size += report->size;
|
||||
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
|
||||
F54_REPORT_DATA_OFFSET, f54->report_data,
|
||||
report_size);
|
||||
if (error) {
|
||||
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
|
||||
__func__, report_size, error);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
abort:
|
||||
|
@ -39,16 +39,16 @@ config TABLET_USB_AIPTEK
|
||||
module will be called aiptek.
|
||||
|
||||
config TABLET_USB_GTCO
|
||||
tristate "GTCO CalComp/InterWrite USB Support"
|
||||
depends on USB && INPUT
|
||||
help
|
||||
Say Y here if you want to use the USB version of the GTCO
|
||||
CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support"
|
||||
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
|
||||
(CONFIG_INPUT_EVDEV) as well.
|
||||
tristate "GTCO CalComp/InterWrite USB Support"
|
||||
depends on USB && INPUT
|
||||
help
|
||||
Say Y here if you want to use the USB version of the GTCO
|
||||
CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support"
|
||||
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
|
||||
(CONFIG_INPUT_EVDEV) as well.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gtco.
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gtco.
|
||||
|
||||
config TABLET_USB_HANWANG
|
||||
tristate "Hanwang Art Master III tablet support (USB)"
|
||||
|
@ -633,7 +633,7 @@ config TOUCHSCREEN_HP600
|
||||
depends on SH_HP6XX && SH_ADC
|
||||
help
|
||||
Say Y here if you have a HP Jornada 620/660/680/690 and want to
|
||||
support the built-in touchscreen.
|
||||
support the built-in touchscreen.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called hp680_ts_input.
|
||||
@ -700,7 +700,6 @@ config TOUCHSCREEN_EDT_FT5X06
|
||||
config TOUCHSCREEN_RASPBERRYPI_FW
|
||||
tristate "Raspberry Pi's firmware base touch screen support"
|
||||
depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have the official Raspberry Pi 7 inch screen on
|
||||
your system.
|
||||
@ -1038,7 +1037,6 @@ config TOUCHSCREEN_TS4800
|
||||
depends on HAS_IOMEM && OF
|
||||
depends on SOC_IMX51 || COMPILE_TEST
|
||||
select MFD_SYSCON
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have a touchscreen on a TS-4800 board.
|
||||
|
||||
@ -1210,7 +1208,6 @@ config TOUCHSCREEN_SUR40
|
||||
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
|
||||
depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
|
||||
depends on VIDEO_V4L2
|
||||
select INPUT_POLLDEV
|
||||
select VIDEOBUF2_DMA_SG
|
||||
help
|
||||
Say Y here if you want support for the Samsung SUR40 touchscreen
|
||||
@ -1246,7 +1243,6 @@ config TOUCHSCREEN_SX8654
|
||||
config TOUCHSCREEN_TPS6507X
|
||||
tristate "TPS6507x based touchscreens"
|
||||
depends on I2C
|
||||
select INPUT_POLLDEV
|
||||
help
|
||||
Say Y here if you have a TPS6507x based touchscreen
|
||||
controller.
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#define AR1021_TOCUH_PKG_SIZE 5
|
||||
#define AR1021_TOUCH_PKG_SIZE 5
|
||||
|
||||
#define AR1021_MAX_X 4095
|
||||
#define AR1021_MAX_Y 4095
|
||||
@ -25,7 +25,7 @@
|
||||
struct ar1021_i2c {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
u8 data[AR1021_TOCUH_PKG_SIZE];
|
||||
u8 data[AR1021_TOUCH_PKG_SIZE];
|
||||
};
|
||||
|
||||
static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id)
|
||||
|
@ -3156,6 +3156,8 @@ static int __maybe_unused mxt_suspend(struct device *dev)
|
||||
|
||||
mutex_unlock(&input_dev->mutex);
|
||||
|
||||
disable_irq(data->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3168,6 +3170,8 @@ static int __maybe_unused mxt_resume(struct device *dev)
|
||||
if (!input_dev)
|
||||
return 0;
|
||||
|
||||
enable_irq(data->irq);
|
||||
|
||||
mutex_lock(&input_dev->mutex);
|
||||
|
||||
if (input_dev->users)
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
#include <linux/iio/types.h>
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define WORK_REGISTER_THRESHOLD 0x00
|
||||
#define WORK_REGISTER_REPORT_RATE 0x08
|
||||
@ -88,6 +89,7 @@ struct edt_ft5x06_ts_data {
|
||||
struct touchscreen_properties prop;
|
||||
u16 num_x;
|
||||
u16 num_y;
|
||||
struct regulator *vcc;
|
||||
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct gpio_desc *wake_gpio;
|
||||
@ -1036,6 +1038,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void edt_ft5x06_disable_regulator(void *arg)
|
||||
{
|
||||
struct edt_ft5x06_ts_data *data = arg;
|
||||
|
||||
regulator_disable(data->vcc);
|
||||
}
|
||||
|
||||
static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -1064,6 +1073,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
|
||||
|
||||
tsdata->max_support_points = chip_data->max_support_points;
|
||||
|
||||
tsdata->vcc = devm_regulator_get(&client->dev, "vcc");
|
||||
if (IS_ERR(tsdata->vcc)) {
|
||||
error = PTR_ERR(tsdata->vcc);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(&client->dev,
|
||||
"failed to request regulator: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = regulator_enable(tsdata->vcc);
|
||||
if (error < 0) {
|
||||
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(&client->dev,
|
||||
edt_ft5x06_disable_regulator,
|
||||
tsdata);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
|
||||
"reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(tsdata->reset_gpio)) {
|
||||
|
@ -1,54 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define ILI210X_TOUCHES 2
|
||||
#define ILI251X_TOUCHES 10
|
||||
#define DEFAULT_POLL_PERIOD 20
|
||||
#define ILI2XXX_POLL_PERIOD 20
|
||||
|
||||
#define ILI210X_DATA_SIZE 64
|
||||
#define ILI211X_DATA_SIZE 43
|
||||
#define ILI251X_DATA_SIZE1 31
|
||||
#define ILI251X_DATA_SIZE2 20
|
||||
|
||||
/* Touchscreen commands */
|
||||
#define REG_TOUCHDATA 0x10
|
||||
#define REG_PANEL_INFO 0x20
|
||||
#define REG_FIRMWARE_VERSION 0x40
|
||||
#define REG_CALIBRATE 0xcc
|
||||
|
||||
struct firmware_version {
|
||||
u8 id;
|
||||
u8 major;
|
||||
u8 minor;
|
||||
} __packed;
|
||||
|
||||
enum ili2xxx_model {
|
||||
MODEL_ILI210X,
|
||||
MODEL_ILI251X,
|
||||
struct ili2xxx_chip {
|
||||
int (*read_reg)(struct i2c_client *client, u8 reg,
|
||||
void *buf, size_t len);
|
||||
int (*get_touch_data)(struct i2c_client *client, u8 *data);
|
||||
bool (*parse_touch_data)(const u8 *data, unsigned int finger,
|
||||
unsigned int *x, unsigned int *y);
|
||||
bool (*continue_polling)(const u8 *data, bool touch);
|
||||
unsigned int max_touches;
|
||||
unsigned int resolution;
|
||||
bool has_calibrate_reg;
|
||||
};
|
||||
|
||||
struct ili210x {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
unsigned int poll_period;
|
||||
struct delayed_work dwork;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct touchscreen_properties prop;
|
||||
enum ili2xxx_model model;
|
||||
unsigned int max_touches;
|
||||
const struct ili2xxx_chip *chip;
|
||||
bool stop;
|
||||
};
|
||||
|
||||
static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
|
||||
size_t len)
|
||||
static int ili210x_read_reg(struct i2c_client *client,
|
||||
u8 reg, void *buf, size_t len)
|
||||
{
|
||||
struct ili210x *priv = i2c_get_clientdata(client);
|
||||
struct i2c_msg msg[2] = {
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
@ -62,53 +62,28 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
int error, ret;
|
||||
|
||||
if (priv->model == MODEL_ILI251X) {
|
||||
if (i2c_transfer(client->adapter, msg, 1) != 1) {
|
||||
dev_err(&client->dev, "i2c transfer failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
usleep_range(5000, 5500);
|
||||
|
||||
if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
|
||||
dev_err(&client->dev, "i2c transfer failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (i2c_transfer(client->adapter, msg, 2) != 2) {
|
||||
dev_err(&client->dev, "i2c transfer failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg)) {
|
||||
error = ret < 0 ? ret : -EIO;
|
||||
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
|
||||
static int ili210x_read_touch_data(struct i2c_client *client, u8 *data)
|
||||
{
|
||||
struct i2c_msg msg = {
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = len,
|
||||
.buf = buf,
|
||||
};
|
||||
|
||||
if (i2c_transfer(client->adapter, &msg, 1) != 1) {
|
||||
dev_err(&client->dev, "i2c transfer failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ili210x_read_reg(client, REG_TOUCHDATA,
|
||||
data, ILI210X_DATA_SIZE);
|
||||
}
|
||||
|
||||
static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
|
||||
static bool ili210x_touchdata_to_coords(const u8 *touchdata,
|
||||
unsigned int finger,
|
||||
unsigned int *x, unsigned int *y)
|
||||
{
|
||||
if (finger >= ILI210X_TOUCHES)
|
||||
return false;
|
||||
|
||||
if (touchdata[0] & BIT(finger))
|
||||
return false;
|
||||
|
||||
@ -118,95 +93,192 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
|
||||
static bool ili210x_check_continue_polling(const u8 *data, bool touch)
|
||||
{
|
||||
return data[0] & 0xf3;
|
||||
}
|
||||
|
||||
static const struct ili2xxx_chip ili210x_chip = {
|
||||
.read_reg = ili210x_read_reg,
|
||||
.get_touch_data = ili210x_read_touch_data,
|
||||
.parse_touch_data = ili210x_touchdata_to_coords,
|
||||
.continue_polling = ili210x_check_continue_polling,
|
||||
.max_touches = 2,
|
||||
.has_calibrate_reg = true,
|
||||
};
|
||||
|
||||
static int ili211x_read_touch_data(struct i2c_client *client, u8 *data)
|
||||
{
|
||||
s16 sum = 0;
|
||||
int error;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE);
|
||||
if (ret != ILI211X_DATA_SIZE) {
|
||||
error = ret < 0 ? ret : -EIO;
|
||||
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* This chip uses custom checksum at the end of data */
|
||||
for (i = 0; i < ILI211X_DATA_SIZE - 1; i++)
|
||||
sum = (sum + data[i]) & 0xff;
|
||||
|
||||
if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) {
|
||||
dev_err(&client->dev,
|
||||
"CRC error (crc=0x%02x expected=0x%02x)\n",
|
||||
sum, data[ILI211X_DATA_SIZE - 1]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ili211x_touchdata_to_coords(const u8 *touchdata,
|
||||
unsigned int finger,
|
||||
unsigned int *x, unsigned int *y)
|
||||
{
|
||||
if (finger >= ILI251X_TOUCHES)
|
||||
u32 data;
|
||||
|
||||
data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0);
|
||||
if (data == 0xffffffff) /* Finger up */
|
||||
return false;
|
||||
|
||||
*x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
|
||||
if (!(*x & BIT(15))) /* Touch indication */
|
||||
*x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
|
||||
touchdata[1 + (finger * 4) + 1];
|
||||
*y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) |
|
||||
touchdata[1 + (finger * 4) + 2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ili211x_decline_polling(const u8 *data, bool touch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct ili2xxx_chip ili211x_chip = {
|
||||
.read_reg = ili210x_read_reg,
|
||||
.get_touch_data = ili211x_read_touch_data,
|
||||
.parse_touch_data = ili211x_touchdata_to_coords,
|
||||
.continue_polling = ili211x_decline_polling,
|
||||
.max_touches = 10,
|
||||
.resolution = 2048,
|
||||
};
|
||||
|
||||
static int ili251x_read_reg(struct i2c_client *client,
|
||||
u8 reg, void *buf, size_t len)
|
||||
{
|
||||
int error;
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_send(client, ®, 1);
|
||||
if (ret == 1) {
|
||||
usleep_range(5000, 5500);
|
||||
|
||||
ret = i2c_master_recv(client, buf, len);
|
||||
if (ret == len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = ret < 0 ? ret : -EIO;
|
||||
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ili251x_read_touch_data(struct i2c_client *client, u8 *data)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = ili251x_read_reg(client, REG_TOUCHDATA,
|
||||
data, ILI251X_DATA_SIZE1);
|
||||
if (!error && data[0] == 2) {
|
||||
error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1,
|
||||
ILI251X_DATA_SIZE2);
|
||||
if (error >= 0 && error != ILI251X_DATA_SIZE2)
|
||||
error = -EIO;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool ili251x_touchdata_to_coords(const u8 *touchdata,
|
||||
unsigned int finger,
|
||||
unsigned int *x, unsigned int *y)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
val = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
|
||||
if (!(val & BIT(15))) /* Touch indication */
|
||||
return false;
|
||||
|
||||
*x &= 0x3fff;
|
||||
*x = val & 0x3fff;
|
||||
*y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ili251x_check_continue_polling(const u8 *data, bool touch)
|
||||
{
|
||||
return touch;
|
||||
}
|
||||
|
||||
static const struct ili2xxx_chip ili251x_chip = {
|
||||
.read_reg = ili251x_read_reg,
|
||||
.get_touch_data = ili251x_read_touch_data,
|
||||
.parse_touch_data = ili251x_touchdata_to_coords,
|
||||
.continue_polling = ili251x_check_continue_polling,
|
||||
.max_touches = 10,
|
||||
.has_calibrate_reg = true,
|
||||
};
|
||||
|
||||
static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
|
||||
{
|
||||
struct input_dev *input = priv->input;
|
||||
int i;
|
||||
bool contact = false, touch = false;
|
||||
bool contact = false, touch;
|
||||
unsigned int x = 0, y = 0;
|
||||
|
||||
for (i = 0; i < priv->max_touches; i++) {
|
||||
if (priv->model == MODEL_ILI210X) {
|
||||
touch = ili210x_touchdata_to_coords(priv, touchdata,
|
||||
i, &x, &y);
|
||||
} else if (priv->model == MODEL_ILI251X) {
|
||||
touch = ili251x_touchdata_to_coords(priv, touchdata,
|
||||
i, &x, &y);
|
||||
if (touch)
|
||||
contact = true;
|
||||
}
|
||||
for (i = 0; i < priv->chip->max_touches; i++) {
|
||||
touch = priv->chip->parse_touch_data(touchdata, i, &x, &y);
|
||||
|
||||
input_mt_slot(input, i);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
|
||||
if (!touch)
|
||||
continue;
|
||||
touchscreen_report_pos(input, &priv->prop, x, y,
|
||||
true);
|
||||
if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) {
|
||||
touchscreen_report_pos(input, &priv->prop, x, y, true);
|
||||
contact = true;
|
||||
}
|
||||
}
|
||||
|
||||
input_mt_report_pointer_emulation(input, false);
|
||||
input_sync(input);
|
||||
|
||||
if (priv->model == MODEL_ILI210X)
|
||||
contact = touchdata[0] & 0xf3;
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
static void ili210x_work(struct work_struct *work)
|
||||
{
|
||||
struct ili210x *priv = container_of(work, struct ili210x,
|
||||
dwork.work);
|
||||
struct i2c_client *client = priv->client;
|
||||
u8 touchdata[64] = { 0 };
|
||||
bool touch;
|
||||
int error = -EINVAL;
|
||||
|
||||
if (priv->model == MODEL_ILI210X) {
|
||||
error = ili210x_read_reg(client, REG_TOUCHDATA,
|
||||
touchdata, sizeof(touchdata));
|
||||
} else if (priv->model == MODEL_ILI251X) {
|
||||
error = ili210x_read_reg(client, REG_TOUCHDATA,
|
||||
touchdata, 31);
|
||||
if (!error && touchdata[0] == 2)
|
||||
error = ili210x_read(client, &touchdata[31], 20);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Unable to get touchdata, err = %d\n", error);
|
||||
return;
|
||||
}
|
||||
|
||||
touch = ili210x_report_events(priv, touchdata);
|
||||
|
||||
if (touch)
|
||||
schedule_delayed_work(&priv->dwork,
|
||||
msecs_to_jiffies(priv->poll_period));
|
||||
}
|
||||
|
||||
static irqreturn_t ili210x_irq(int irq, void *irq_data)
|
||||
{
|
||||
struct ili210x *priv = irq_data;
|
||||
struct i2c_client *client = priv->client;
|
||||
const struct ili2xxx_chip *chip = priv->chip;
|
||||
u8 touchdata[ILI210X_DATA_SIZE] = { 0 };
|
||||
bool keep_polling;
|
||||
bool touch;
|
||||
int error;
|
||||
|
||||
schedule_delayed_work(&priv->dwork, 0);
|
||||
do {
|
||||
error = chip->get_touch_data(client, touchdata);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Unable to get touch data: %d\n", error);
|
||||
break;
|
||||
}
|
||||
|
||||
touch = ili210x_report_events(priv, touchdata);
|
||||
keep_polling = chip->continue_polling(touchdata, touch);
|
||||
if (keep_polling)
|
||||
msleep(ILI2XXX_POLL_PERIOD);
|
||||
} while (!priv->stop && keep_polling);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -242,8 +314,19 @@ static struct attribute *ili210x_attributes[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static umode_t ili210x_calibrate_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int index)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ili210x *priv = i2c_get_clientdata(client);
|
||||
|
||||
return priv->chip->has_calibrate_reg;
|
||||
}
|
||||
|
||||
static const struct attribute_group ili210x_attr_group = {
|
||||
.attrs = ili210x_attributes,
|
||||
.is_visible = ili210x_calibrate_visible,
|
||||
};
|
||||
|
||||
static void ili210x_power_down(void *data)
|
||||
@ -253,28 +336,35 @@ static void ili210x_power_down(void *data)
|
||||
gpiod_set_value_cansleep(reset_gpio, 1);
|
||||
}
|
||||
|
||||
static void ili210x_cancel_work(void *data)
|
||||
static void ili210x_stop(void *data)
|
||||
{
|
||||
struct ili210x *priv = data;
|
||||
|
||||
cancel_delayed_work_sync(&priv->dwork);
|
||||
/* Tell ISR to quit even if there is a contact. */
|
||||
priv->stop = true;
|
||||
}
|
||||
|
||||
static int ili210x_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
const struct ili2xxx_chip *chip;
|
||||
struct ili210x *priv;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct input_dev *input;
|
||||
struct firmware_version firmware;
|
||||
enum ili2xxx_model model;
|
||||
int error;
|
||||
|
||||
model = (enum ili2xxx_model)id->driver_data;
|
||||
unsigned int max_xy;
|
||||
|
||||
dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
|
||||
|
||||
chip = device_get_match_data(dev);
|
||||
if (!chip && id)
|
||||
chip = (const struct ili2xxx_chip *)id->driver_data;
|
||||
if (!chip) {
|
||||
dev_err(&client->dev, "unknown device model\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (client->irq <= 0) {
|
||||
dev_err(dev, "No IRQ!\n");
|
||||
return -EINVAL;
|
||||
@ -305,49 +395,39 @@ static int ili210x_i2c_probe(struct i2c_client *client,
|
||||
|
||||
priv->client = client;
|
||||
priv->input = input;
|
||||
priv->poll_period = DEFAULT_POLL_PERIOD;
|
||||
INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
|
||||
priv->reset_gpio = reset_gpio;
|
||||
priv->model = model;
|
||||
if (model == MODEL_ILI210X)
|
||||
priv->max_touches = ILI210X_TOUCHES;
|
||||
if (model == MODEL_ILI251X)
|
||||
priv->max_touches = ILI251X_TOUCHES;
|
||||
|
||||
priv->chip = chip;
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
/* Get firmware version */
|
||||
error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
|
||||
&firmware, sizeof(firmware));
|
||||
if (error) {
|
||||
dev_err(dev, "Failed to get firmware version, err: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Setup input device */
|
||||
input->name = "ILI210x Touchscreen";
|
||||
input->id.bustype = BUS_I2C;
|
||||
input->dev.parent = dev;
|
||||
|
||||
/* Multi touch */
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
|
||||
max_xy = (chip->resolution ?: SZ_64K) - 1;
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0);
|
||||
touchscreen_parse_properties(input, true, &priv->prop);
|
||||
input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
|
||||
|
||||
error = devm_add_action(dev, ili210x_cancel_work, priv);
|
||||
if (error)
|
||||
error = input_mt_init_slots(input, priv->chip->max_touches,
|
||||
INPUT_MT_DIRECT);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to set up slots, err: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
|
||||
client->name, priv);
|
||||
error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
|
||||
IRQF_ONESHOT, client->name, priv);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(dev, ili210x_stop, priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = devm_device_add_group(dev, &ili210x_attr_group);
|
||||
if (error) {
|
||||
dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
|
||||
@ -361,56 +441,28 @@ static int ili210x_i2c_probe(struct i2c_client *client,
|
||||
return error;
|
||||
}
|
||||
|
||||
device_init_wakeup(dev, 1);
|
||||
|
||||
dev_dbg(dev,
|
||||
"ILI210x initialized (IRQ: %d), firmware version %d.%d.%d",
|
||||
client->irq, firmware.id, firmware.major, firmware.minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
enable_irq_wake(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused ili210x_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
if (device_may_wakeup(&client->dev))
|
||||
disable_irq_wake(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
|
||||
ili210x_i2c_suspend, ili210x_i2c_resume);
|
||||
|
||||
static const struct i2c_device_id ili210x_i2c_id[] = {
|
||||
{ "ili210x", MODEL_ILI210X },
|
||||
{ "ili251x", MODEL_ILI251X },
|
||||
{ "ili210x", (long)&ili210x_chip },
|
||||
{ "ili2117", (long)&ili211x_chip },
|
||||
{ "ili251x", (long)&ili251x_chip },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
|
||||
|
||||
static const struct of_device_id ili210x_dt_ids[] = {
|
||||
{ .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
|
||||
{ .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
|
||||
{ },
|
||||
{ .compatible = "ilitek,ili210x", .data = &ili210x_chip },
|
||||
{ .compatible = "ilitek,ili2117", .data = &ili211x_chip },
|
||||
{ .compatible = "ilitek,ili251x", .data = &ili251x_chip },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
|
||||
|
||||
static struct i2c_driver ili210x_ts_driver = {
|
||||
.driver = {
|
||||
.name = "ili210x_i2c",
|
||||
.pm = &ili210x_i2c_pm,
|
||||
.of_match_table = ili210x_dt_ids,
|
||||
},
|
||||
.id_table = ili210x_i2c_id,
|
||||
|
@ -446,8 +446,7 @@ static int mms114_probe(struct i2c_client *client,
|
||||
data->client = client;
|
||||
data->input_dev = input_dev;
|
||||
|
||||
/* FIXME: switch to device_get_match_data() when available */
|
||||
match_data = of_device_get_match_data(&client->dev);
|
||||
match_data = device_get_match_data(&client->dev);
|
||||
if (!match_data)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -5,22 +5,73 @@
|
||||
* Copyright (C) 2010-2011 Pixcir, Inc.
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_data/pixcir_i2c_ts.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
|
||||
|
||||
/*
|
||||
* Register map
|
||||
*/
|
||||
#define PIXCIR_REG_POWER_MODE 51
|
||||
#define PIXCIR_REG_INT_MODE 52
|
||||
|
||||
/*
|
||||
* Power modes:
|
||||
* active: max scan speed
|
||||
* idle: lower scan speed with automatic transition to active on touch
|
||||
* halt: datasheet says sleep but this is more like halt as the chip
|
||||
* clocks are cut and it can only be brought out of this mode
|
||||
* using the RESET pin.
|
||||
*/
|
||||
enum pixcir_power_mode {
|
||||
PIXCIR_POWER_ACTIVE,
|
||||
PIXCIR_POWER_IDLE,
|
||||
PIXCIR_POWER_HALT,
|
||||
};
|
||||
|
||||
#define PIXCIR_POWER_MODE_MASK 0x03
|
||||
#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
|
||||
|
||||
/*
|
||||
* Interrupt modes:
|
||||
* periodical: interrupt is asserted periodicaly
|
||||
* diff coordinates: interrupt is asserted when coordinates change
|
||||
* level on touch: interrupt level asserted during touch
|
||||
* pulse on touch: interrupt pulse asserted during touch
|
||||
*
|
||||
*/
|
||||
enum pixcir_int_mode {
|
||||
PIXCIR_INT_PERIODICAL,
|
||||
PIXCIR_INT_DIFF_COORD,
|
||||
PIXCIR_INT_LEVEL_TOUCH,
|
||||
PIXCIR_INT_PULSE_TOUCH,
|
||||
};
|
||||
|
||||
#define PIXCIR_INT_MODE_MASK 0x03
|
||||
#define PIXCIR_INT_ENABLE (1UL << 3)
|
||||
#define PIXCIR_INT_POL_HIGH (1UL << 2)
|
||||
|
||||
/**
|
||||
* struct pixcir_i2c_chip_data - chip related data
|
||||
* @max_fingers: Max number of fingers reported simultaneously by h/w
|
||||
* @has_hw_ids: Hardware supports finger tracking IDs
|
||||
*
|
||||
*/
|
||||
struct pixcir_i2c_chip_data {
|
||||
u8 max_fingers;
|
||||
bool has_hw_ids;
|
||||
};
|
||||
|
||||
struct pixcir_i2c_ts_data {
|
||||
struct i2c_client *client;
|
||||
struct input_dev *input;
|
||||
@ -30,7 +81,6 @@ struct pixcir_i2c_ts_data {
|
||||
struct gpio_desc *gpio_wake;
|
||||
const struct pixcir_i2c_chip_data *chip;
|
||||
struct touchscreen_properties prop;
|
||||
int max_fingers; /* Max fingers supported in this instance */
|
||||
bool running;
|
||||
};
|
||||
|
||||
@ -54,7 +104,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
|
||||
memset(report, 0, sizeof(struct pixcir_report_data));
|
||||
|
||||
i = chip->has_hw_ids ? 1 : 0;
|
||||
readsize = 2 + tsdata->max_fingers * (4 + i);
|
||||
readsize = 2 + tsdata->chip->max_fingers * (4 + i);
|
||||
if (readsize > sizeof(rdbuf))
|
||||
readsize = sizeof(rdbuf);
|
||||
|
||||
@ -75,8 +125,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
|
||||
}
|
||||
|
||||
touch = rdbuf[0] & 0x7;
|
||||
if (touch > tsdata->max_fingers)
|
||||
touch = tsdata->max_fingers;
|
||||
if (touch > tsdata->chip->max_fingers)
|
||||
touch = tsdata->chip->max_fingers;
|
||||
|
||||
report->num_touches = touch;
|
||||
bufptr = &rdbuf[2];
|
||||
@ -192,7 +242,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
|
||||
|
||||
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't read reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_POWER_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -205,7 +255,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
|
||||
|
||||
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't write reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_POWER_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -231,7 +281,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
|
||||
|
||||
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't read reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_INT_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -246,7 +296,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
|
||||
|
||||
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't write reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_INT_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -264,7 +314,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
|
||||
|
||||
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't read reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_INT_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -276,7 +326,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
|
||||
|
||||
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
|
||||
dev_err(dev, "%s: can't write reg %d : %d\n",
|
||||
__func__, PIXCIR_REG_INT_MODE, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -412,31 +462,9 @@ unlock:
|
||||
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
|
||||
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pixcir_of_match[];
|
||||
|
||||
static int pixcir_parse_dt(struct device *dev,
|
||||
struct pixcir_i2c_ts_data *tsdata)
|
||||
{
|
||||
tsdata->chip = of_device_get_match_data(dev);
|
||||
if (!tsdata->chip)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int pixcir_parse_dt(struct device *dev,
|
||||
struct pixcir_i2c_ts_data *tsdata)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct pixcir_ts_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
struct device *dev = &client->dev;
|
||||
struct pixcir_i2c_ts_data *tsdata;
|
||||
struct input_dev *input;
|
||||
@ -446,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
if (!tsdata)
|
||||
return -ENOMEM;
|
||||
|
||||
if (pdata) {
|
||||
tsdata->chip = &pdata->chip;
|
||||
} else if (dev->of_node) {
|
||||
error = pixcir_parse_dt(dev, tsdata);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
dev_err(dev, "platform data not defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!tsdata->chip->max_fingers) {
|
||||
dev_err(dev, "Invalid max_fingers in chip data\n");
|
||||
tsdata->chip = device_get_match_data(dev);
|
||||
if (!tsdata->chip && id)
|
||||
tsdata->chip = (const void *)id->driver_data;
|
||||
if (!tsdata->chip) {
|
||||
dev_err(dev, "can't locate chip data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -475,30 +495,17 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
input->id.bustype = BUS_I2C;
|
||||
input->open = pixcir_input_open;
|
||||
input->close = pixcir_input_close;
|
||||
input->dev.parent = dev;
|
||||
|
||||
if (pdata) {
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
|
||||
} else {
|
||||
input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
|
||||
input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
|
||||
touchscreen_parse_properties(input, true, &tsdata->prop);
|
||||
if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
|
||||
!input_abs_get_max(input, ABS_MT_POSITION_Y)) {
|
||||
dev_err(dev, "Touchscreen size is not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
|
||||
input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
|
||||
touchscreen_parse_properties(input, true, &tsdata->prop);
|
||||
if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
|
||||
!input_abs_get_max(input, ABS_MT_POSITION_Y)) {
|
||||
dev_err(dev, "Touchscreen size is not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tsdata->max_fingers = tsdata->chip->max_fingers;
|
||||
if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
|
||||
tsdata->max_fingers = PIXCIR_MAX_SLOTS;
|
||||
dev_info(dev, "Limiting maximum fingers to %d\n",
|
||||
tsdata->max_fingers);
|
||||
}
|
||||
|
||||
error = input_mt_init_slots(input, tsdata->max_fingers,
|
||||
error = input_mt_init_slots(input, tsdata->chip->max_fingers,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
|
||||
if (error) {
|
||||
dev_err(dev, "Error initializing Multi-Touch slots\n");
|
||||
@ -510,7 +517,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
|
||||
if (IS_ERR(tsdata->gpio_attb)) {
|
||||
error = PTR_ERR(tsdata->gpio_attb);
|
||||
dev_err(dev, "Failed to request ATTB gpio: %d\n", error);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to request ATTB gpio: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -518,7 +527,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(tsdata->gpio_reset)) {
|
||||
error = PTR_ERR(tsdata->gpio_reset);
|
||||
dev_err(dev, "Failed to request RESET gpio: %d\n", error);
|
||||
if (error != -EPROBE_DEFER)
|
||||
dev_err(dev, "Failed to request RESET gpio: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -574,14 +585,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
|
||||
{ "pixcir_ts", 0 },
|
||||
{ "pixcir_tangoc", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct pixcir_i2c_chip_data pixcir_ts_data = {
|
||||
.max_fingers = 2,
|
||||
/* no hw id support */
|
||||
@ -592,6 +595,14 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
|
||||
.has_hw_ids = true,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
|
||||
{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
|
||||
{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id pixcir_of_match[] = {
|
||||
{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
|
||||
{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <soc/bcm2835/raspberrypi-firmware.h>
|
||||
|
||||
@ -34,7 +33,7 @@
|
||||
|
||||
struct rpi_ts {
|
||||
struct platform_device *pdev;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct touchscreen_properties prop;
|
||||
|
||||
void __iomem *fw_regs_va;
|
||||
@ -57,10 +56,9 @@ struct rpi_ts_regs {
|
||||
} point[RPI_TS_MAX_SUPPORTED_POINTS];
|
||||
};
|
||||
|
||||
static void rpi_ts_poll(struct input_polled_dev *dev)
|
||||
static void rpi_ts_poll(struct input_dev *input)
|
||||
{
|
||||
struct input_dev *input = dev->input;
|
||||
struct rpi_ts *ts = dev->private;
|
||||
struct rpi_ts *ts = input_get_drvdata(input);
|
||||
struct rpi_ts_regs regs;
|
||||
int modified_ids = 0;
|
||||
long released_ids;
|
||||
@ -123,10 +121,9 @@ static int rpi_ts_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct device_node *fw_node;
|
||||
struct rpi_firmware *fw;
|
||||
struct input_dev *input;
|
||||
struct rpi_ts *ts;
|
||||
u32 touchbuf;
|
||||
int error;
|
||||
@ -160,7 +157,6 @@ static int rpi_ts_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
touchbuf = (u32)ts->fw_regs_phys;
|
||||
error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
|
||||
&touchbuf, sizeof(touchbuf));
|
||||
@ -170,19 +166,17 @@ static int rpi_ts_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(dev);
|
||||
if (!poll_dev) {
|
||||
input = devm_input_allocate_device(dev);
|
||||
if (!input) {
|
||||
dev_err(dev, "Failed to allocate input device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
ts->poll_dev = poll_dev;
|
||||
input = poll_dev->input;
|
||||
|
||||
ts->input = input;
|
||||
input_set_drvdata(input, ts);
|
||||
|
||||
input->name = "raspberrypi-ts";
|
||||
input->id.bustype = BUS_HOST;
|
||||
poll_dev->poll_interval = RPI_TS_POLL_INTERVAL;
|
||||
poll_dev->poll = rpi_ts_poll;
|
||||
poll_dev->private = ts;
|
||||
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, 0,
|
||||
RPI_TS_DEFAULT_WIDTH, 0, 0);
|
||||
@ -197,7 +191,15 @@ static int rpi_ts_probe(struct platform_device *pdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_setup_polling(input, rpi_ts_poll);
|
||||
if (error) {
|
||||
dev_err(dev, "could not set up polling mode, %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input, RPI_TS_POLL_INTERVAL);
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(dev, "could not register input device, %d\n", error);
|
||||
return error;
|
||||
@ -214,10 +216,10 @@ MODULE_DEVICE_TABLE(of, rpi_ts_match);
|
||||
|
||||
static struct platform_driver rpi_ts_driver = {
|
||||
.driver = {
|
||||
.name = "raspberrypi-ts",
|
||||
.name = "raspberrypi-ts",
|
||||
.of_match_table = rpi_ts_match,
|
||||
},
|
||||
.probe = rpi_ts_probe,
|
||||
.probe = rpi_ts_probe,
|
||||
};
|
||||
module_platform_driver(rpi_ts_driver);
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -14,23 +14,19 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/input/touchscreen.h>
|
||||
|
||||
#define ST1232_TS_NAME "st1232-ts"
|
||||
#define ST1633_TS_NAME "st1633-ts"
|
||||
|
||||
struct st1232_ts_finger {
|
||||
u16 x;
|
||||
u16 y;
|
||||
u8 t;
|
||||
bool is_valid;
|
||||
};
|
||||
#define ST_TS_MAX_FINGERS 10
|
||||
|
||||
struct st_chip_info {
|
||||
bool have_z;
|
||||
@ -50,81 +46,89 @@ struct st1232_ts_data {
|
||||
const struct st_chip_info *chip_info;
|
||||
int read_buf_len;
|
||||
u8 *read_buf;
|
||||
struct st1232_ts_finger *finger;
|
||||
};
|
||||
|
||||
static int st1232_ts_read_data(struct st1232_ts_data *ts)
|
||||
{
|
||||
struct st1232_ts_finger *finger = ts->finger;
|
||||
struct i2c_client *client = ts->client;
|
||||
struct i2c_msg msg[2];
|
||||
int error;
|
||||
int i, y;
|
||||
u8 start_reg = ts->chip_info->start_reg;
|
||||
u8 *buf = ts->read_buf;
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.len = sizeof(start_reg),
|
||||
.buf = &start_reg,
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD | I2C_M_DMA_SAFE,
|
||||
.len = ts->read_buf_len,
|
||||
.buf = ts->read_buf,
|
||||
}
|
||||
};
|
||||
int ret;
|
||||
|
||||
/* read touchscreen data */
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 1;
|
||||
msg[0].buf = &start_reg;
|
||||
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
|
||||
if (ret != ARRAY_SIZE(msg))
|
||||
return ret < 0 ? ret : -EIO;
|
||||
|
||||
msg[1].addr = ts->client->addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].len = ts->read_buf_len;
|
||||
msg[1].buf = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
error = i2c_transfer(client->adapter, msg, 2);
|
||||
if (error < 0)
|
||||
return error;
|
||||
static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
|
||||
{
|
||||
struct input_dev *input = ts->input_dev;
|
||||
struct input_mt_pos pos[ST_TS_MAX_FINGERS];
|
||||
u8 z[ST_TS_MAX_FINGERS];
|
||||
int slots[ST_TS_MAX_FINGERS];
|
||||
int n_contacts = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) {
|
||||
finger[i].is_valid = buf[i + y] >> 7;
|
||||
if (finger[i].is_valid) {
|
||||
finger[i].x = ((buf[i + y] & 0x0070) << 4) |
|
||||
buf[i + y + 1];
|
||||
finger[i].y = ((buf[i + y] & 0x0007) << 8) |
|
||||
buf[i + y + 2];
|
||||
for (i = 0; i < ts->chip_info->max_fingers; i++) {
|
||||
u8 *buf = &ts->read_buf[i * 4];
|
||||
|
||||
if (buf[0] & BIT(7)) {
|
||||
unsigned int x = ((buf[0] & 0x70) << 4) | buf[1];
|
||||
unsigned int y = ((buf[0] & 0x07) << 8) | buf[2];
|
||||
|
||||
touchscreen_set_mt_pos(&pos[n_contacts],
|
||||
&ts->prop, x, y);
|
||||
|
||||
/* st1232 includes a z-axis / touch strength */
|
||||
if (ts->chip_info->have_z)
|
||||
finger[i].t = buf[i + 6];
|
||||
z[n_contacts] = ts->read_buf[i + 6];
|
||||
|
||||
n_contacts++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
input_mt_assign_slots(input, slots, pos, n_contacts, 0);
|
||||
for (i = 0; i < n_contacts; i++) {
|
||||
input_mt_slot(input, slots[i]);
|
||||
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
|
||||
input_report_abs(input, ABS_MT_POSITION_X, pos[i].x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, pos[i].y);
|
||||
if (ts->chip_info->have_z)
|
||||
input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]);
|
||||
}
|
||||
|
||||
input_mt_sync_frame(input);
|
||||
input_sync(input);
|
||||
|
||||
return n_contacts;
|
||||
}
|
||||
|
||||
static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct st1232_ts_data *ts = dev_id;
|
||||
struct st1232_ts_finger *finger = ts->finger;
|
||||
struct input_dev *input_dev = ts->input_dev;
|
||||
int count = 0;
|
||||
int i, ret;
|
||||
int count;
|
||||
int error;
|
||||
|
||||
ret = st1232_ts_read_data(ts);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
error = st1232_ts_read_data(ts);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* multi touch protocol */
|
||||
for (i = 0; i < ts->chip_info->max_fingers; i++) {
|
||||
if (!finger[i].is_valid)
|
||||
continue;
|
||||
|
||||
if (ts->chip_info->have_z)
|
||||
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
|
||||
finger[i].t);
|
||||
|
||||
touchscreen_report_pos(input_dev, &ts->prop,
|
||||
finger[i].x, finger[i].y, true);
|
||||
input_mt_sync(input_dev);
|
||||
count++;
|
||||
}
|
||||
|
||||
/* SYN_MT_REPORT only if no contact */
|
||||
count = st1232_ts_parse_and_report(ts);
|
||||
if (!count) {
|
||||
input_mt_sync(input_dev);
|
||||
if (ts->low_latency_req.dev) {
|
||||
dev_pm_qos_remove_request(&ts->low_latency_req);
|
||||
ts->low_latency_req.dev = NULL;
|
||||
@ -136,10 +140,7 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
|
||||
DEV_PM_QOS_RESUME_LATENCY, 100);
|
||||
}
|
||||
|
||||
/* SYN_REPORT */
|
||||
input_sync(input_dev);
|
||||
|
||||
end:
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -149,6 +150,11 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
|
||||
gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
|
||||
}
|
||||
|
||||
static void st1232_ts_power_off(void *data)
|
||||
{
|
||||
st1232_ts_power(data, false);
|
||||
}
|
||||
|
||||
static const struct st_chip_info st1232_chip_info = {
|
||||
.have_z = true,
|
||||
.max_x = 0x31f, /* 800 - 1 */
|
||||
@ -172,7 +178,6 @@ static int st1232_ts_probe(struct i2c_client *client,
|
||||
{
|
||||
const struct st_chip_info *match;
|
||||
struct st1232_ts_data *ts;
|
||||
struct st1232_ts_finger *finger;
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
@ -199,11 +204,6 @@ static int st1232_ts_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
ts->chip_info = match;
|
||||
ts->finger = devm_kcalloc(&client->dev,
|
||||
ts->chip_info->max_fingers, sizeof(*finger),
|
||||
GFP_KERNEL);
|
||||
if (!ts->finger)
|
||||
return -ENOMEM;
|
||||
|
||||
/* allocate a buffer according to the number of registers to read */
|
||||
ts->read_buf_len = ts->chip_info->max_fingers * 4;
|
||||
@ -229,14 +229,15 @@ static int st1232_ts_probe(struct i2c_client *client,
|
||||
|
||||
st1232_ts_power(ts, true);
|
||||
|
||||
error = devm_add_action_or_reset(&client->dev, st1232_ts_power_off, ts);
|
||||
if (error) {
|
||||
dev_err(&client->dev,
|
||||
"Failed to install power off action: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
input_dev->name = "st1232-touchscreen";
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->dev.parent = &client->dev;
|
||||
|
||||
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
|
||||
__set_bit(EV_SYN, input_dev->evbit);
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
|
||||
if (ts->chip_info->have_z)
|
||||
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
|
||||
@ -249,6 +250,14 @@ static int st1232_ts_probe(struct i2c_client *client,
|
||||
|
||||
touchscreen_parse_properties(input_dev, true, &ts->prop);
|
||||
|
||||
error = input_mt_init_slots(input_dev, ts->chip_info->max_fingers,
|
||||
INPUT_MT_DIRECT | INPUT_MT_TRACK |
|
||||
INPUT_MT_DROP_UNUSED);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "failed to initialize MT slots\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
error = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, st1232_ts_irq_handler,
|
||||
IRQF_ONESHOT,
|
||||
@ -266,16 +275,6 @@ static int st1232_ts_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, ts);
|
||||
device_init_wakeup(&client->dev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int st1232_ts_remove(struct i2c_client *client)
|
||||
{
|
||||
struct st1232_ts_data *ts = i2c_get_clientdata(client);
|
||||
|
||||
st1232_ts_power(ts, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -285,12 +284,10 @@ static int __maybe_unused st1232_ts_suspend(struct device *dev)
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct st1232_ts_data *ts = i2c_get_clientdata(client);
|
||||
|
||||
if (device_may_wakeup(&client->dev)) {
|
||||
enable_irq_wake(client->irq);
|
||||
} else {
|
||||
disable_irq(client->irq);
|
||||
disable_irq(client->irq);
|
||||
|
||||
if (!device_may_wakeup(&client->dev))
|
||||
st1232_ts_power(ts, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -300,12 +297,10 @@ static int __maybe_unused st1232_ts_resume(struct device *dev)
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct st1232_ts_data *ts = i2c_get_clientdata(client);
|
||||
|
||||
if (device_may_wakeup(&client->dev)) {
|
||||
disable_irq_wake(client->irq);
|
||||
} else {
|
||||
if (!device_may_wakeup(&client->dev))
|
||||
st1232_ts_power(ts, true);
|
||||
enable_irq(client->irq);
|
||||
}
|
||||
|
||||
enable_irq(client->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -329,7 +324,6 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
|
||||
|
||||
static struct i2c_driver st1232_ts_driver = {
|
||||
.probe = st1232_ts_probe,
|
||||
.remove = st1232_ts_remove,
|
||||
.id_table = st1232_ts_id,
|
||||
.driver = {
|
||||
.name = ST1232_TS_NAME,
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <linux/videodev2.h>
|
||||
@ -206,7 +206,7 @@ struct sur40_state {
|
||||
|
||||
struct usb_device *usbdev;
|
||||
struct device *dev;
|
||||
struct input_polled_dev *input;
|
||||
struct input_dev *input;
|
||||
|
||||
struct v4l2_device v4l2;
|
||||
struct video_device vdev;
|
||||
@ -370,6 +370,10 @@ static int sur40_init(struct sur40_state *dev)
|
||||
goto error;
|
||||
|
||||
result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12);
|
||||
if (result < 0)
|
||||
goto error;
|
||||
|
||||
result = 0;
|
||||
|
||||
/*
|
||||
* Discard the result buffer - no known data inside except
|
||||
@ -381,22 +385,22 @@ error:
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback routines from input_polled_dev
|
||||
* Callback routines from input_dev
|
||||
*/
|
||||
|
||||
/* Enable the device, polling will now start. */
|
||||
static void sur40_open(struct input_polled_dev *polldev)
|
||||
static int sur40_open(struct input_dev *input)
|
||||
{
|
||||
struct sur40_state *sur40 = polldev->private;
|
||||
struct sur40_state *sur40 = input_get_drvdata(input);
|
||||
|
||||
dev_dbg(sur40->dev, "open\n");
|
||||
sur40_init(sur40);
|
||||
return sur40_init(sur40);
|
||||
}
|
||||
|
||||
/* Disable device, polling has stopped. */
|
||||
static void sur40_close(struct input_polled_dev *polldev)
|
||||
static void sur40_close(struct input_dev *input)
|
||||
{
|
||||
struct sur40_state *sur40 = polldev->private;
|
||||
struct sur40_state *sur40 = input_get_drvdata(input);
|
||||
|
||||
dev_dbg(sur40->dev, "close\n");
|
||||
/*
|
||||
@ -448,10 +452,9 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
|
||||
}
|
||||
|
||||
/* core function: poll for new input data */
|
||||
static void sur40_poll(struct input_polled_dev *polldev)
|
||||
static void sur40_poll(struct input_dev *input)
|
||||
{
|
||||
struct sur40_state *sur40 = polldev->private;
|
||||
struct input_dev *input = polldev->input;
|
||||
struct sur40_state *sur40 = input_get_drvdata(input);
|
||||
int result, bulk_read, need_blobs, packet_blobs, i;
|
||||
u32 uninitialized_var(packet_id);
|
||||
|
||||
@ -613,10 +616,9 @@ err_poll:
|
||||
}
|
||||
|
||||
/* Initialize input device parameters. */
|
||||
static void sur40_input_setup(struct input_dev *input_dev)
|
||||
static int sur40_input_setup_events(struct input_dev *input_dev)
|
||||
{
|
||||
__set_bit(EV_KEY, input_dev->evbit);
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
int error;
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
|
||||
0, SENSOR_RES_X, 0, 0);
|
||||
@ -637,8 +639,14 @@ static void sur40_input_setup(struct input_dev *input_dev)
|
||||
|
||||
input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||
|
||||
input_mt_init_slots(input_dev, MAX_CONTACTS,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
|
||||
error = input_mt_init_slots(input_dev, MAX_CONTACTS,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
|
||||
if (error) {
|
||||
dev_err(input_dev->dev.parent, "failed to set up slots\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check candidate USB interface. */
|
||||
@ -649,7 +657,7 @@ static int sur40_probe(struct usb_interface *interface,
|
||||
struct sur40_state *sur40;
|
||||
struct usb_host_interface *iface_desc;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
int error;
|
||||
|
||||
/* Check if we really have the right interface. */
|
||||
@ -670,8 +678,8 @@ static int sur40_probe(struct usb_interface *interface,
|
||||
if (!sur40)
|
||||
return -ENOMEM;
|
||||
|
||||
poll_dev = input_allocate_polled_device();
|
||||
if (!poll_dev) {
|
||||
input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_dev;
|
||||
}
|
||||
@ -681,26 +689,33 @@ static int sur40_probe(struct usb_interface *interface,
|
||||
spin_lock_init(&sur40->qlock);
|
||||
mutex_init(&sur40->lock);
|
||||
|
||||
/* Set up polled input device control structure */
|
||||
poll_dev->private = sur40;
|
||||
poll_dev->poll_interval = POLL_INTERVAL;
|
||||
poll_dev->open = sur40_open;
|
||||
poll_dev->poll = sur40_poll;
|
||||
poll_dev->close = sur40_close;
|
||||
|
||||
/* Set up regular input device structure */
|
||||
sur40_input_setup(poll_dev->input);
|
||||
|
||||
poll_dev->input->name = DRIVER_LONG;
|
||||
usb_to_input_id(usbdev, &poll_dev->input->id);
|
||||
input->name = DRIVER_LONG;
|
||||
usb_to_input_id(usbdev, &input->id);
|
||||
usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
|
||||
strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
|
||||
poll_dev->input->phys = sur40->phys;
|
||||
poll_dev->input->dev.parent = &interface->dev;
|
||||
input->phys = sur40->phys;
|
||||
input->dev.parent = &interface->dev;
|
||||
|
||||
input->open = sur40_open;
|
||||
input->close = sur40_close;
|
||||
|
||||
error = sur40_input_setup_events(input);
|
||||
if (error)
|
||||
goto err_free_input;
|
||||
|
||||
input_set_drvdata(input, sur40);
|
||||
error = input_setup_polling(input, sur40_poll);
|
||||
if (error) {
|
||||
dev_err(&interface->dev, "failed to set up polling");
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input, POLL_INTERVAL);
|
||||
|
||||
sur40->usbdev = usbdev;
|
||||
sur40->dev = &interface->dev;
|
||||
sur40->input = poll_dev;
|
||||
sur40->input = input;
|
||||
|
||||
/* use the bulk-in endpoint tested above */
|
||||
sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
|
||||
@ -709,11 +724,11 @@ static int sur40_probe(struct usb_interface *interface,
|
||||
if (!sur40->bulk_in_buffer) {
|
||||
dev_err(&interface->dev, "Unable to allocate input buffer.");
|
||||
error = -ENOMEM;
|
||||
goto err_free_polldev;
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
/* register the polled input device */
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_register_device(input);
|
||||
if (error) {
|
||||
dev_err(&interface->dev,
|
||||
"Unable to register polled input device.");
|
||||
@ -796,8 +811,8 @@ err_unreg_v4l2:
|
||||
v4l2_device_unregister(&sur40->v4l2);
|
||||
err_free_buffer:
|
||||
kfree(sur40->bulk_in_buffer);
|
||||
err_free_polldev:
|
||||
input_free_polled_device(sur40->input);
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
err_free_dev:
|
||||
kfree(sur40);
|
||||
|
||||
@ -813,8 +828,7 @@ static void sur40_disconnect(struct usb_interface *interface)
|
||||
video_unregister_device(&sur40->vdev);
|
||||
v4l2_device_unregister(&sur40->v4l2);
|
||||
|
||||
input_unregister_polled_device(sur40->input);
|
||||
input_free_polled_device(sur40->input);
|
||||
input_unregister_device(sur40->input);
|
||||
kfree(sur40->bulk_in_buffer);
|
||||
kfree(sur40);
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/tps6507x.h>
|
||||
#include <linux/input/tps6507x-ts.h>
|
||||
@ -40,7 +39,7 @@ struct ts_event {
|
||||
|
||||
struct tps6507x_ts {
|
||||
struct device *dev;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct tps6507x_dev *mfd;
|
||||
char phys[32];
|
||||
struct ts_event tc;
|
||||
@ -148,10 +147,9 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tps6507x_ts_poll(struct input_polled_dev *poll_dev)
|
||||
static void tps6507x_ts_poll(struct input_dev *input_dev)
|
||||
{
|
||||
struct tps6507x_ts *tsc = poll_dev->private;
|
||||
struct input_dev *input_dev = poll_dev->input;
|
||||
struct tps6507x_ts *tsc = input_get_drvdata(input_dev);
|
||||
bool pendown;
|
||||
s32 ret;
|
||||
|
||||
@ -205,7 +203,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
const struct tps6507x_board *tps_board;
|
||||
const struct touchscreen_init_data *init_data;
|
||||
struct tps6507x_ts *tsc;
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
@ -240,23 +237,16 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
snprintf(tsc->phys, sizeof(tsc->phys),
|
||||
"%s/input0", dev_name(tsc->dev));
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(&pdev->dev);
|
||||
if (!poll_dev) {
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input_dev) {
|
||||
dev_err(tsc->dev, "Failed to allocate polled input device.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tsc->poll_dev = poll_dev;
|
||||
|
||||
poll_dev->private = tsc;
|
||||
poll_dev->poll = tps6507x_ts_poll;
|
||||
poll_dev->poll_interval = init_data ?
|
||||
init_data->poll_period : TSC_DEFAULT_POLL_PERIOD;
|
||||
|
||||
input_dev = poll_dev->input;
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
tsc->input = input_dev;
|
||||
input_set_drvdata(input_dev, tsc);
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
|
||||
@ -275,7 +265,15 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
error = input_setup_polling(input_dev, tps6507x_ts_poll);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
input_set_poll_interval(input_dev,
|
||||
init_data ? init_data->poll_period :
|
||||
TSC_DEFAULT_POLL_PERIOD);
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input-polldev.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
@ -33,7 +32,7 @@
|
||||
#define Y_OFFSET 0x2
|
||||
|
||||
struct ts4800_ts {
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input;
|
||||
struct device *dev;
|
||||
char phys[32];
|
||||
|
||||
@ -46,22 +45,26 @@ struct ts4800_ts {
|
||||
int debounce;
|
||||
};
|
||||
|
||||
static void ts4800_ts_open(struct input_polled_dev *dev)
|
||||
static int ts4800_ts_open(struct input_dev *input_dev)
|
||||
{
|
||||
struct ts4800_ts *ts = dev->private;
|
||||
int ret;
|
||||
struct ts4800_ts *ts = input_get_drvdata(input_dev);
|
||||
int error;
|
||||
|
||||
ts->pendown = false;
|
||||
ts->debounce = DEBOUNCE_COUNT;
|
||||
|
||||
ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit);
|
||||
if (ret)
|
||||
dev_warn(ts->dev, "Failed to enable touchscreen\n");
|
||||
error = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit);
|
||||
if (error) {
|
||||
dev_warn(ts->dev, "Failed to enable touchscreen: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ts4800_ts_close(struct input_polled_dev *dev)
|
||||
static void ts4800_ts_close(struct input_dev *input_dev)
|
||||
{
|
||||
struct ts4800_ts *ts = dev->private;
|
||||
struct ts4800_ts *ts = input_get_drvdata(input_dev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, 0);
|
||||
@ -70,10 +73,9 @@ static void ts4800_ts_close(struct input_polled_dev *dev)
|
||||
|
||||
}
|
||||
|
||||
static void ts4800_ts_poll(struct input_polled_dev *dev)
|
||||
static void ts4800_ts_poll(struct input_dev *input_dev)
|
||||
{
|
||||
struct input_dev *input_dev = dev->input;
|
||||
struct ts4800_ts *ts = dev->private;
|
||||
struct ts4800_ts *ts = input_get_drvdata(input_dev);
|
||||
u16 last_x = readw(ts->base + X_OFFSET);
|
||||
u16 last_y = readw(ts->base + Y_OFFSET);
|
||||
bool pendown = last_x & PENDOWN_MASK;
|
||||
@ -146,7 +148,7 @@ static int ts4800_parse_dt(struct platform_device *pdev,
|
||||
|
||||
static int ts4800_ts_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct input_polled_dev *poll_dev;
|
||||
struct input_dev *input_dev;
|
||||
struct ts4800_ts *ts;
|
||||
int error;
|
||||
|
||||
@ -162,32 +164,38 @@ static int ts4800_ts_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(ts->base))
|
||||
return PTR_ERR(ts->base);
|
||||
|
||||
poll_dev = devm_input_allocate_polled_device(&pdev->dev);
|
||||
if (!poll_dev)
|
||||
input_dev = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&pdev->dev));
|
||||
ts->poll_dev = poll_dev;
|
||||
ts->input = input_dev;
|
||||
ts->dev = &pdev->dev;
|
||||
|
||||
poll_dev->private = ts;
|
||||
poll_dev->poll_interval = POLL_INTERVAL;
|
||||
poll_dev->open = ts4800_ts_open;
|
||||
poll_dev->close = ts4800_ts_close;
|
||||
poll_dev->poll = ts4800_ts_poll;
|
||||
input_set_drvdata(input_dev, ts);
|
||||
|
||||
poll_dev->input->name = "TS-4800 Touchscreen";
|
||||
poll_dev->input->phys = ts->phys;
|
||||
input_dev->name = "TS-4800 Touchscreen";
|
||||
input_dev->phys = ts->phys;
|
||||
|
||||
input_set_capability(poll_dev->input, EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(poll_dev->input, ABS_X, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(poll_dev->input, ABS_Y, 0, MAX_12BIT, 0, 0);
|
||||
input_dev->open = ts4800_ts_open;
|
||||
input_dev->close = ts4800_ts_close;
|
||||
|
||||
error = input_register_polled_device(poll_dev);
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
|
||||
|
||||
error = input_setup_polling(input_dev, ts4800_ts_poll);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "Unable to set up polling: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
input_set_poll_interval(input_dev, POLL_INTERVAL);
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev,
|
||||
"Unabled to register polled input device (%d)\n",
|
||||
error);
|
||||
"Unable to register input device: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define WACOM_CMD_QUERY0 0x04
|
||||
|
@ -383,6 +383,7 @@ int input_setup_polling(struct input_dev *dev,
|
||||
void input_set_poll_interval(struct input_dev *dev, unsigned int interval);
|
||||
void input_set_min_poll_interval(struct input_dev *dev, unsigned int interval);
|
||||
void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval);
|
||||
int input_get_poll_interval(struct input_dev *dev);
|
||||
|
||||
int __must_check input_register_handler(struct input_handler *);
|
||||
void input_unregister_handler(struct input_handler *);
|
||||
|
@ -1,64 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _PIXCIR_I2C_TS_H
|
||||
#define _PIXCIR_I2C_TS_H
|
||||
|
||||
/*
|
||||
* Register map
|
||||
*/
|
||||
#define PIXCIR_REG_POWER_MODE 51
|
||||
#define PIXCIR_REG_INT_MODE 52
|
||||
|
||||
/*
|
||||
* Power modes:
|
||||
* active: max scan speed
|
||||
* idle: lower scan speed with automatic transition to active on touch
|
||||
* halt: datasheet says sleep but this is more like halt as the chip
|
||||
* clocks are cut and it can only be brought out of this mode
|
||||
* using the RESET pin.
|
||||
*/
|
||||
enum pixcir_power_mode {
|
||||
PIXCIR_POWER_ACTIVE,
|
||||
PIXCIR_POWER_IDLE,
|
||||
PIXCIR_POWER_HALT,
|
||||
};
|
||||
|
||||
#define PIXCIR_POWER_MODE_MASK 0x03
|
||||
#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
|
||||
|
||||
/*
|
||||
* Interrupt modes:
|
||||
* periodical: interrupt is asserted periodicaly
|
||||
* diff coordinates: interrupt is asserted when coordinates change
|
||||
* level on touch: interrupt level asserted during touch
|
||||
* pulse on touch: interrupt pulse asserted druing touch
|
||||
*
|
||||
*/
|
||||
enum pixcir_int_mode {
|
||||
PIXCIR_INT_PERIODICAL,
|
||||
PIXCIR_INT_DIFF_COORD,
|
||||
PIXCIR_INT_LEVEL_TOUCH,
|
||||
PIXCIR_INT_PULSE_TOUCH,
|
||||
};
|
||||
|
||||
#define PIXCIR_INT_MODE_MASK 0x03
|
||||
#define PIXCIR_INT_ENABLE (1UL << 3)
|
||||
#define PIXCIR_INT_POL_HIGH (1UL << 2)
|
||||
|
||||
/**
|
||||
* struct pixcir_irc_chip_data - chip related data
|
||||
* @max_fingers: Max number of fingers reported simultaneously by h/w
|
||||
* @has_hw_ids: Hardware supports finger tracking IDs
|
||||
*
|
||||
*/
|
||||
struct pixcir_i2c_chip_data {
|
||||
u8 max_fingers;
|
||||
bool has_hw_ids;
|
||||
};
|
||||
|
||||
struct pixcir_ts_platform_data {
|
||||
int x_max;
|
||||
int y_max;
|
||||
struct pixcir_i2c_chip_data chip;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user