1
0
Fork 0

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
  ...
alistair/sunxi64-5.5-dsi
Linus Torvalds 2019-12-01 18:45:29 -08:00
commit 72c0870e3a
56 changed files with 1650 additions and 1895 deletions

View File

@ -157,6 +157,15 @@ Required properties:
Optional properties: Optional properties:
- timeout-sec: contains the watchdog timeout in seconds. - 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): Example (imx8qxp):
------------- -------------
aliases { aliases {
@ -220,6 +229,11 @@ firmware {
compatible = "fsl,imx8qxp-sc-rtc"; compatible = "fsl,imx8qxp-sc-rtc";
}; };
scu_key: scu-key {
compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key";
linux,keycodes = <KEY_POWER>;
};
watchdog { watchdog {
compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt"; compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt";
timeout-sec = <60>; timeout-sec = <60>;

View File

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

View File

@ -1,8 +1,9 @@
Ilitek ILI210x/ILI251x touchscreen controller Ilitek ILI210x/ILI2117/ILI251x touchscreen controller
Required properties: Required properties:
- compatible: - compatible:
ilitek,ili210x for ILI210x ilitek,ili210x for ILI210x
ilitek,ili2117 for ILI2117
ilitek,ili251x for ILI251x ilitek,ili251x for ILI251x
- reg: The I2C address of the device - reg: The I2C address of the device

View 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

View File

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

View File

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

View File

@ -10,13 +10,13 @@ Documentation/devicetree/bindings/mfd/mt6397.txt
Required properties: Required properties:
- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys" - 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: Optional Properties:
- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt - wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
- mediatek,long-press-mode: Long press key shutdown setting, 1 for - mediatek,long-press-mode: Long press key shutdown setting, 1 for
pwrkey only, 2 for pwrkey/homekey together, others for disabled. 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: Example:

View File

@ -15,7 +15,7 @@ Optional properties:
- st,onkey-pu-inactive: onkey pull up is not active - st,onkey-pu-inactive: onkey pull up is not active
- power-off-time-sec: Duration in seconds which the key should be kept - 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). 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: Example:

View File

@ -38,7 +38,7 @@ Optional properties:
Example: Example:
ad7879@2c { touchscreen0@2c {
compatible = "adi,ad7879-1"; compatible = "adi,ad7879-1";
reg = <0x2c>; reg = <0x2c>;
interrupt-parent = <&gpio1>; interrupt-parent = <&gpio1>;
@ -52,7 +52,7 @@ Example:
adi,conversion-interval = /bits/ 8 <255>; adi,conversion-interval = /bits/ 8 <255>;
}; };
ad7879@1 { touchscreen1@1 {
compatible = "adi,ad7879"; compatible = "adi,ad7879";
spi-max-frequency = <5000000>; spi-max-frequency = <5000000>;
reg = <1>; reg = <1>;

View File

@ -30,6 +30,7 @@ Required properties:
Optional properties: Optional properties:
- reset-gpios: GPIO specification for the RESET input - reset-gpios: GPIO specification for the RESET input
- wake-gpios: GPIO specification for the WAKE input - wake-gpios: GPIO specification for the WAKE input
- vcc-supply: Regulator that supplies the touchscreen
- pinctrl-names: should be "default" - pinctrl-names: should be "default"
- pinctrl-0: a phandle pointing to the pin settings for the - pinctrl-0: a phandle pointing to the pin settings for the

View File

@ -123,6 +123,15 @@ void input_set_max_poll_interval(struct input_dev *dev, unsigned int interval)
} }
EXPORT_SYMBOL(input_set_max_poll_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 */ /* SYSFS interface */
static ssize_t input_dev_get_poll_interval(struct device *dev, static ssize_t input_dev_get_poll_interval(struct device *dev,

View File

@ -334,7 +334,6 @@ config JOYSTICK_MAPLE
config JOYSTICK_PSXPAD_SPI config JOYSTICK_PSXPAD_SPI
tristate "PlayStation 1/2 joypads via SPI interface" tristate "PlayStation 1/2 joypads via SPI interface"
depends on SPI depends on SPI
select INPUT_POLLDEV
help help
Say Y here if you wish to connect PlayStation 1/2 joypads Say Y here if you wish to connect PlayStation 1/2 joypads
via SPI interface. via SPI interface.

View File

@ -22,7 +22,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/types.h> #include <linux/types.h>
@ -60,7 +59,7 @@ static const u8 PSX_CMD_ENABLE_MOTOR[] = {
struct psxpad { struct psxpad {
struct spi_device *spi; struct spi_device *spi;
struct input_polled_dev *pdev; struct input_dev *idev;
char phys[0x20]; char phys[0x20];
bool motor1enable; bool motor1enable;
bool motor2enable; 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, static int psxpad_spi_play_effect(struct input_dev *idev,
void *data, struct ff_effect *effect) void *data, struct ff_effect *effect)
{ {
struct input_polled_dev *pdev = input_get_drvdata(idev); struct psxpad *pad = input_get_drvdata(idev);
struct psxpad *pad = pdev->private;
switch (effect->type) { switch (effect->type) {
case FF_RUMBLE: case FF_RUMBLE:
@ -158,10 +156,9 @@ static int psxpad_spi_init_ff(struct psxpad *pad)
{ {
int err; 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, err = input_ff_create_memless(pad->idev, NULL, psxpad_spi_play_effect);
psxpad_spi_play_effect);
if (err) { if (err) {
dev_err(&pad->spi->dev, dev_err(&pad->spi->dev,
"input_ff_create_memless() failed: %d\n", err); "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 */ #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); 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); 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 psxpad *pad = input_get_drvdata(input);
struct input_dev *input = pdev->input;
u8 b_rsp3, b_rsp4; u8 b_rsp3, b_rsp4;
int err; 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) static int psxpad_spi_probe(struct spi_device *spi)
{ {
struct psxpad *pad; struct psxpad *pad;
struct input_polled_dev *pdev;
struct input_dev *idev; struct input_dev *idev;
int err; int err;
@ -292,31 +289,26 @@ static int psxpad_spi_probe(struct spi_device *spi)
if (!pad) if (!pad)
return -ENOMEM; return -ENOMEM;
pdev = input_allocate_polled_device(); idev = devm_input_allocate_device(&spi->dev);
if (!pdev) { if (!idev) {
dev_err(&spi->dev, "failed to allocate input device\n"); dev_err(&spi->dev, "failed to allocate input device\n");
return -ENOMEM; return -ENOMEM;
} }
/* input poll device settings */ /* input poll device settings */
pad->pdev = pdev; pad->idev = idev;
pad->spi = spi; 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 */ /* input device settings */
idev = pdev->input; input_set_drvdata(idev, pad);
idev->name = "PlayStation 1/2 joypad"; idev->name = "PlayStation 1/2 joypad";
snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev)); snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev));
idev->id.bustype = BUS_SPI; idev->id.bustype = BUS_SPI;
idev->open = psxpad_spi_poll_open;
idev->close = psxpad_spi_poll_close;
/* key/value map settings */ /* key/value map settings */
input_set_abs_params(idev, ABS_X, 0, 255, 0, 0); input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
input_set_abs_params(idev, ABS_Y, 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 */ /* pad settings */
psxpad_set_motor_level(pad, 0, 0); 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 */ /* register input poll device */
err = input_register_polled_device(pdev); err = input_register_device(idev);
if (err) { if (err) {
dev_err(&spi->dev, dev_err(&spi->dev,
"failed to register input poll device: %d\n", err); "failed to register input device: %d\n", err);
return err; return err;
} }

View File

@ -16,7 +16,6 @@ if INPUT_KEYBOARD
config KEYBOARD_ADC config KEYBOARD_ADC
tristate "ADC Ladder Buttons" tristate "ADC Ladder Buttons"
depends on IIO depends on IIO
select INPUT_POLLDEV
help help
This driver implements support for buttons connected This driver implements support for buttons connected
to an ADC using a resistor ladder. to an ADC using a resistor ladder.
@ -168,14 +167,14 @@ config KEYBOARD_QT1050
the module will be called qt1050 the module will be called qt1050
config KEYBOARD_QT1070 config KEYBOARD_QT1070
tristate "Atmel AT42QT1070 Touch Sensor Chip" tristate "Atmel AT42QT1070 Touch Sensor Chip"
depends on I2C depends on I2C
help help
Say Y here if you want to use Atmel AT42QT1070 QTouch Say Y here if you want to use Atmel AT42QT1070 QTouch
Sensor chip as input device. Sensor chip as input device.
To compile this driver as a module, choose M here: To compile this driver as a module, choose M here:
the module will be called qt1070 the module will be called qt1070
config KEYBOARD_QT2160 config KEYBOARD_QT2160
tristate "Atmel AT42QT2160 Touch Sensor Chip" tristate "Atmel AT42QT2160 Touch Sensor Chip"
@ -191,7 +190,6 @@ config KEYBOARD_CLPS711X
tristate "CLPS711X Keypad support" tristate "CLPS711X Keypad support"
depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST) depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
select INPUT_POLLDEV
help help
Say Y here to enable the matrix keypad on the Cirrus Logic Say Y here to enable the matrix keypad on the Cirrus Logic
CLPS711X CPUs. CLPS711X CPUs.
@ -250,7 +248,6 @@ config KEYBOARD_GPIO
config KEYBOARD_GPIO_POLLED config KEYBOARD_GPIO_POLLED
tristate "Polled GPIO buttons" tristate "Polled GPIO buttons"
depends on GPIOLIB depends on GPIOLIB
select INPUT_POLLDEV
help help
This driver implements support for buttons connected This driver implements support for buttons connected
to GPIO pins that are not capable of generating interrupts. to GPIO pins that are not capable of generating interrupts.
@ -342,7 +339,6 @@ config KEYBOARD_HIL
config KEYBOARD_HP6XX config KEYBOARD_HP6XX
tristate "HP Jornada 6xx keyboard" tristate "HP Jornada 6xx keyboard"
depends on SH_HP6XX depends on SH_HP6XX
select INPUT_POLLDEV
help help
Say Y here if you have a HP Jornada 620/660/680/690 and want to Say Y here if you have a HP Jornada 620/660/680/690 and want to
support the built-in keyboard. support the built-in keyboard.
@ -469,6 +465,16 @@ config KEYBOARD_IMX
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called imx_keypad. 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 config KEYBOARD_NEWTON
tristate "Newton keyboard" tristate "Newton keyboard"
select SERIO select SERIO

View File

@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.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_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o

View File

@ -9,7 +9,6 @@
#include <linux/iio/consumer.h> #include <linux/iio/consumer.h>
#include <linux/iio/types.h> #include <linux/iio/types.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
@ -30,9 +29,9 @@ struct adc_keys_state {
const struct adc_keys_button *map; 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; int i, value, ret;
u32 diff, closest = 0xffffffff; u32 diff, closest = 0xffffffff;
int keycode = 0; int keycode = 0;
@ -55,12 +54,12 @@ static void adc_keys_poll(struct input_polled_dev *dev)
keycode = 0; keycode = 0;
if (st->last_key && st->last_key != keycode) 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) 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; st->last_key = keycode;
} }
@ -108,7 +107,6 @@ static int adc_keys_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct adc_keys_state *st; struct adc_keys_state *st;
struct input_polled_dev *poll_dev;
struct input_dev *input; struct input_dev *input;
enum iio_chan_type type; enum iio_chan_type type;
int i, value; int i, value;
@ -145,19 +143,13 @@ static int adc_keys_probe(struct platform_device *pdev)
if (error) if (error)
return error; return error;
poll_dev = devm_input_allocate_polled_device(dev); input = devm_input_allocate_device(dev);
if (!poll_dev) { if (!input) {
dev_err(dev, "failed to allocate input device\n"); dev_err(dev, "failed to allocate input device\n");
return -ENOMEM; return -ENOMEM;
} }
if (!device_property_read_u32(dev, "poll-interval", &value)) input_set_drvdata(input, st);
poll_dev->poll_interval = value;
poll_dev->poll = adc_keys_poll;
poll_dev->private = st;
input = poll_dev->input;
input->name = pdev->name; input->name = pdev->name;
input->phys = "adc-keys/input0"; 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")) if (device_property_read_bool(dev, "autorepeat"))
__set_bit(EV_REP, input->evbit); __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) { if (error) {
dev_err(dev, "Unable to register input device: %d\n", error); dev_err(dev, "Unable to register input device: %d\n", error);
return error; return error;

View File

@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
input_sync(kpad->input); input_sync(kpad->input);
} }
static int adp5589_probe(struct i2c_client *client, static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
const struct i2c_device_id *id)
{ {
struct adp5589_kpad *kpad; struct i2c_client *client = kpad->client;
const struct adp5589_kpad_platform_data *pdata = const struct adp5589_kpad_platform_data *pdata =
dev_get_platdata(&client->dev); dev_get_platdata(&client->dev);
struct input_dev *input; struct input_dev *input;
unsigned int revid; unsigned int i;
int ret, i;
int error; 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) && if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
(pdata->keypad_en_mask >> kpad->var->col_shift)) || (pdata->keypad_en_mask >> kpad->var->col_shift)) ||
!pdata->keymap) { !pdata->keymap) {
dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
if (pdata->keymapsize != kpad->var->keymapsize) { if (pdata->keymapsize != kpad->var->keymapsize) {
dev_err(&client->dev, "invalid keymapsize\n"); dev_err(&client->dev, "invalid keymapsize\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
if (!pdata->gpimap && pdata->gpimapsize) { if (!pdata->gpimap && pdata->gpimapsize) {
dev_err(&client->dev, "invalid gpimap from pdata\n"); dev_err(&client->dev, "invalid gpimap from pdata\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
if (pdata->gpimapsize > kpad->var->gpimapsize_max) { if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
dev_err(&client->dev, "invalid gpimapsize\n"); dev_err(&client->dev, "invalid gpimapsize\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
for (i = 0; i < pdata->gpimapsize; i++) { 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 || if (pin < kpad->var->gpi_pin_base ||
pin > kpad->var->gpi_pin_end) { pin > kpad->var->gpi_pin_end) {
dev_err(&client->dev, "invalid gpi pin data\n"); dev_err(&client->dev, "invalid gpi pin data\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
if ((1 << (pin - kpad->var->gpi_pin_row_base)) & if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
pdata->keypad_en_mask) { pdata->keypad_en_mask) {
dev_err(&client->dev, "invalid gpi row/col data\n"); dev_err(&client->dev, "invalid gpi row/col data\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
} }
if (!client->irq) { if (!client->irq) {
dev_err(&client->dev, "no IRQ?\n"); dev_err(&client->dev, "no IRQ?\n");
error = -EINVAL; return -EINVAL;
goto err_free_mem;
} }
input = input_allocate_device(); input = input_allocate_device();
if (!input) { if (!input)
error = -ENOMEM; return -ENOMEM;
goto err_free_mem;
}
kpad->client = client;
kpad->input = input; 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->name = client->name;
input->phys = "adp5589-keys/input0"; input->phys = "adp5589-keys/input0";
input->dev.parent = &client->dev; input->dev.parent = &client->dev;
@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
goto err_unreg_dev; 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); error = adp5589_setup(kpad);
if (error) if (error)
goto err_free_irq; goto err_keypad_remove;
if (kpad->gpimapsize) if (kpad->gpimapsize)
adp5589_report_switch_state(kpad); adp5589_report_switch_state(kpad);
error = adp5589_gpio_add(kpad); error = adp5589_gpio_add(kpad);
if (error) if (error)
goto err_free_irq; goto err_keypad_remove;
device_init_wakeup(&client->dev, 1);
i2c_set_clientdata(client, kpad); i2c_set_clientdata(client, kpad);
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
return 0; return 0;
err_free_irq: err_keypad_remove:
free_irq(client->irq, kpad); adp5589_keypad_remove(kpad);
err_unreg_dev:
input_unregister_device(input);
input = NULL;
err_free_input:
input_free_device(input);
err_free_mem: err_free_mem:
kfree(kpad); kfree(kpad);
@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
struct adp5589_kpad *kpad = i2c_get_clientdata(client); struct adp5589_kpad *kpad = i2c_get_clientdata(client);
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
free_irq(client->irq, kpad); adp5589_keypad_remove(kpad);
input_unregister_device(kpad->input);
adp5589_gpio_remove(kpad); adp5589_gpio_remove(kpad);
kfree(kpad); kfree(kpad);
@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
struct adp5589_kpad *kpad = dev_get_drvdata(dev); struct adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client; struct i2c_client *client = kpad->client;
if (!kpad->input)
return 0;
disable_irq(client->irq); disable_irq(client->irq);
if (device_may_wakeup(&client->dev)) 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 adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client; struct i2c_client *client = kpad->client;
if (!kpad->input)
return 0;
if (device_may_wakeup(&client->dev)) if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq); disable_irq_wake(client->irq);

View File

@ -6,7 +6,6 @@
*/ */
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -30,10 +29,10 @@ struct clps711x_keypad_data {
struct clps711x_gpio_data *gpio_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; const unsigned short *keycodes = input->keycode;
struct clps711x_keypad_data *priv = dev->private; struct clps711x_keypad_data *priv = input_get_drvdata(input);
bool sync = false; bool sync = false;
int col, row; int col, row;
@ -61,14 +60,14 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
if (state) { if (state) {
set_bit(col, data->last_state); set_bit(col, data->last_state);
input_event(dev->input, EV_MSC, input_event(input,
MSC_SCAN, code); EV_MSC, MSC_SCAN, code);
} else { } else {
clear_bit(col, data->last_state); clear_bit(col, data->last_state);
} }
if (keycodes[code]) if (keycodes[code])
input_report_key(dev->input, input_report_key(input,
keycodes[code], state); keycodes[code], state);
sync = true; sync = true;
} }
@ -80,7 +79,7 @@ static void clps711x_keypad_poll(struct input_polled_dev *dev)
} }
if (sync) if (sync)
input_sync(dev->input); input_sync(input);
} }
static int clps711x_keypad_probe(struct platform_device *pdev) 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 clps711x_keypad_data *priv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct input_polled_dev *poll_dev; struct input_dev *input;
u32 poll_interval; u32 poll_interval;
int i, err; int i, err;
@ -125,53 +124,43 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
if (err) if (err)
return err; return err;
poll_dev = input_allocate_polled_device(); input = devm_input_allocate_device(dev);
if (!poll_dev) if (!input)
return -ENOMEM; return -ENOMEM;
poll_dev->private = priv; input_set_drvdata(input, priv);
poll_dev->poll = clps711x_keypad_poll;
poll_dev->poll_interval = poll_interval; input->name = pdev->name;
poll_dev->input->name = pdev->name; input->dev.parent = dev;
poll_dev->input->dev.parent = dev; input->id.bustype = BUS_HOST;
poll_dev->input->id.bustype = BUS_HOST; input->id.vendor = 0x0001;
poll_dev->input->id.vendor = 0x0001; input->id.product = 0x0001;
poll_dev->input->id.product = 0x0001; input->id.version = 0x0100;
poll_dev->input->id.version = 0x0100;
err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count, err = matrix_keypad_build_keymap(NULL, NULL, priv->row_count,
CLPS711X_KEYPAD_COL_COUNT, CLPS711X_KEYPAD_COL_COUNT,
NULL, poll_dev->input); NULL, input);
if (err) 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")) if (of_property_read_bool(np, "autorepeat"))
__set_bit(EV_REP, poll_dev->input->evbit); __set_bit(EV_REP, input->evbit);
platform_set_drvdata(pdev, poll_dev);
/* Set all columns to low */ /* Set all columns to low */
regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK, regmap_update_bits(priv->syscon, SYSCON_OFFSET, SYSCON1_KBDSCAN_MASK,
SYSCON1_KBDSCAN(1)); SYSCON1_KBDSCAN(1));
err = input_register_polled_device(poll_dev);
err = input_setup_polling(input, clps711x_keypad_poll);
if (err) if (err)
goto out_err; return err;
return 0; input_set_poll_interval(input, poll_interval);
out_err: err = input_register_device(input);
input_free_polled_device(poll_dev); if (err)
return err; 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);
return 0; return 0;
} }
@ -188,7 +177,6 @@ static struct platform_driver clps711x_keypad_driver = {
.of_match_table = clps711x_keypad_of_match, .of_match_table = clps711x_keypad_of_match,
}, },
.probe = clps711x_keypad_probe, .probe = clps711x_keypad_probe,
.remove = clps711x_keypad_remove,
}; };
module_platform_driver(clps711x_keypad_driver); module_platform_driver(clps711x_keypad_driver);

View File

@ -494,10 +494,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
spin_lock_init(&bdata->lock); spin_lock_init(&bdata->lock);
if (child) { if (child) {
bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
child, NULL, GPIOD_IN, desc);
GPIOD_IN,
desc);
if (IS_ERR(bdata->gpiod)) { if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod); error = PTR_ERR(bdata->gpiod);
if (error == -ENOENT) { if (error == -ENOENT) {

View File

@ -16,7 +16,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
@ -34,7 +33,7 @@ struct gpio_keys_button_data {
}; };
struct gpio_keys_polled_dev { struct gpio_keys_polled_dev {
struct input_polled_dev *poll_dev; struct input_dev *input;
struct device *dev; struct device *dev;
const struct gpio_keys_platform_data *pdata; const struct gpio_keys_platform_data *pdata;
unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)]; 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]; 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, const struct gpio_keys_button *button,
int state) int state)
{ {
struct gpio_keys_polled_dev *bdev = dev->private; struct gpio_keys_polled_dev *bdev = input_get_drvdata(input);
struct input_dev *input = dev->input;
unsigned int type = button->type ?: EV_KEY; unsigned int type = button->type ?: EV_KEY;
if (type == EV_REL) { 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, const struct gpio_keys_button *button,
struct gpio_keys_button_data *bdata) 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); state = gpiod_get_value_cansleep(bdata->gpiod);
if (state < 0) { if (state < 0) {
dev_err(dev->input->dev.parent, dev_err(input->dev.parent,
"failed to get gpio state: %d\n", state); "failed to get gpio state: %d\n", state);
} else { } else {
gpio_keys_button_event(dev, button, state); gpio_keys_button_event(input, button, state);
if (state != bdata->last_state) { if (state != bdata->last_state) {
bdata->count = 0; 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; const struct gpio_keys_platform_data *pdata = bdev->pdata;
struct input_dev *input = dev->input;
int i; int i;
memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen)); 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) { if (bdata->count < bdata->threshold) {
bdata->count++; bdata->count++;
gpio_keys_button_event(dev, &pdata->buttons[i], gpio_keys_button_event(input, &pdata->buttons[i],
bdata->last_state); bdata->last_state);
} else { } else {
gpio_keys_polled_check_state(dev, &pdata->buttons[i], gpio_keys_polled_check_state(input, &pdata->buttons[i],
bdata); bdata);
} }
} }
@ -122,18 +119,20 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
input_sync(input); 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; const struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->enable) if (pdata->enable)
pdata->enable(bdev->dev); 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; const struct gpio_keys_platform_data *pdata = bdev->pdata;
if (pdata->disable) if (pdata->disable)
@ -232,7 +231,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
struct fwnode_handle *child = NULL; struct fwnode_handle *child = NULL;
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
struct gpio_keys_polled_dev *bdev; struct gpio_keys_polled_dev *bdev;
struct input_polled_dev *poll_dev;
struct input_dev *input; struct input_dev *input;
int error; int error;
int i; int i;
@ -255,19 +253,13 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
poll_dev = devm_input_allocate_polled_device(dev); input = devm_input_allocate_device(dev);
if (!poll_dev) { if (!input) {
dev_err(dev, "no memory for polled device\n"); dev_err(dev, "no memory for input device\n");
return -ENOMEM; return -ENOMEM;
} }
poll_dev->private = bdev; input_set_drvdata(input, 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->name = pdata->name ?: pdev->name; input->name = pdata->name ?: pdev->name;
input->phys = DRV_NAME"/input0"; 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.product = 0x0001;
input->id.version = 0x0100; input->id.version = 0x0100;
input->open = gpio_keys_polled_open;
input->close = gpio_keys_polled_close;
__set_bit(EV_KEY, input->evbit); __set_bit(EV_KEY, input->evbit);
if (pdata->rep) if (pdata->rep)
__set_bit(EV_REP, input->evbit); __set_bit(EV_REP, input->evbit);
@ -300,10 +295,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, bdata->gpiod = devm_fwnode_gpiod_get(dev, child,
NULL, child, NULL, GPIOD_IN,
GPIOD_IN, button->desc);
button->desc);
if (IS_ERR(bdata->gpiod)) { if (IS_ERR(bdata->gpiod)) {
error = PTR_ERR(bdata->gpiod); error = PTR_ERR(bdata->gpiod);
if (error != -EPROBE_DEFER) if (error != -EPROBE_DEFER)
@ -353,11 +347,19 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
fwnode_handle_put(child); fwnode_handle_put(child);
bdev->poll_dev = poll_dev; bdev->input = input;
bdev->dev = dev; bdev->dev = dev;
bdev->pdata = pdata; 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) { if (error) {
dev_err(dev, "unable to register polled device, err=%d\n", dev_err(dev, "unable to register polled device, err=%d\n",
error); error);
@ -366,7 +368,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
/* report initial state of the buttons */ /* report initial state of the buttons */
for (i = 0; i < pdata->nbuttons; i++) 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]); &bdev->data[i]);
input_sync(input); input_sync(input);

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

View File

@ -15,7 +15,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
@ -64,7 +63,7 @@ static const unsigned short jornada_scancodes[] = {
#define JORNADA_SCAN_SIZE 18 #define JORNADA_SCAN_SIZE 18
struct jornadakbd { struct jornadakbd {
struct input_polled_dev *poll_dev; struct input_dev *input;
unsigned short keymap[ARRAY_SIZE(jornada_scancodes)]; unsigned short keymap[ARRAY_SIZE(jornada_scancodes)];
unsigned char length; unsigned char length;
unsigned char old_scan[JORNADA_SCAN_SIZE]; unsigned char old_scan[JORNADA_SCAN_SIZE];
@ -73,7 +72,7 @@ struct jornadakbd {
static void jornada_parse_kbd(struct jornadakbd *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 short *keymap = jornadakbd->keymap;
unsigned int sync_me = 0; unsigned int sync_me = 0;
unsigned int i, j; unsigned int i, j;
@ -167,9 +166,9 @@ static void jornada_scan_keyb(unsigned char *s)
*s++ = __raw_readb(PHDR); *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_scan_keyb(jornadakbd->new_scan);
jornada_parse_kbd(jornadakbd); 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) static int jornada680kbd_probe(struct platform_device *pdev)
{ {
struct jornadakbd *jornadakbd; struct jornadakbd *jornadakbd;
struct input_polled_dev *poll_dev;
struct input_dev *input_dev; struct input_dev *input_dev;
int i, error; int i, error;
@ -188,29 +186,24 @@ static int jornada680kbd_probe(struct platform_device *pdev)
if (!jornadakbd) if (!jornadakbd)
return -ENOMEM; return -ENOMEM;
poll_dev = devm_input_allocate_polled_device(&pdev->dev); input_dev = devm_input_allocate_device(&pdev->dev);
if (!poll_dev) { if (!input_dev) {
dev_err(&pdev->dev, "failed to allocate polled input device\n"); dev_err(&pdev->dev, "failed to allocate input device\n");
return -ENOMEM; return -ENOMEM;
} }
jornadakbd->poll_dev = poll_dev; jornadakbd->input = input_dev;
memcpy(jornadakbd->keymap, jornada_scancodes, memcpy(jornadakbd->keymap, jornada_scancodes,
sizeof(jornadakbd->keymap)); sizeof(jornadakbd->keymap));
poll_dev->private = jornadakbd; input_set_drvdata(input_dev, jornadakbd);
poll_dev->poll = jornadakbd680_poll;
poll_dev->poll_interval = 50; /* msec */
input_dev = poll_dev->input;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->name = "HP Jornada 680 keyboard"; input_dev->name = "HP Jornada 680 keyboard";
input_dev->phys = "jornadakbd/input0"; input_dev->phys = "jornadakbd/input0";
input_dev->keycode = jornadakbd->keymap; input_dev->keycode = jornadakbd->keymap;
input_dev->keycodesize = sizeof(unsigned short); input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes); input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes);
input_dev->dev.parent = &pdev->dev;
input_dev->id.bustype = BUS_HOST; input_dev->id.bustype = BUS_HOST;
for (i = 0; i < 128; i++) 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); 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) { 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; return error;
} }

View File

@ -54,6 +54,9 @@
/* MPR121 has 12 keys */ /* MPR121 has 12 keys */
#define MPR121_MAX_KEY_COUNT 12 #define MPR121_MAX_KEY_COUNT 12
#define MPR121_MIN_POLL_INTERVAL 10
#define MPR121_MAX_POLL_INTERVAL 200
struct mpr121_touchkey { struct mpr121_touchkey {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input_dev; struct input_dev *input_dev;
@ -115,11 +118,11 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
return vdd_supply; 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 mpr121_touchkey *mpr121 = input_get_drvdata(dev);
struct i2c_client *client = mpr121->client;
struct input_dev *input = mpr121->input_dev; struct input_dev *input = mpr121->input_dev;
struct i2c_client *client = mpr121->client;
unsigned long bit_changed; unsigned long bit_changed;
unsigned int key_num; unsigned int key_num;
int reg; 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); reg = i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_1_ADDR);
if (reg < 0) { if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg); dev_err(&client->dev, "i2c read error [%d]\n", reg);
goto out; return;
} }
reg <<= 8; reg <<= 8;
reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR); reg |= i2c_smbus_read_byte_data(client, ELE_TOUCH_STATUS_0_ADDR);
if (reg < 0) { if (reg < 0) {
dev_err(&client->dev, "i2c read error [%d]\n", reg); dev_err(&client->dev, "i2c read error [%d]\n", reg);
goto out; return;
} }
reg &= TOUCH_STATUS_MASK; reg &= TOUCH_STATUS_MASK;
@ -155,8 +158,14 @@ static irqreturn_t mpr_touchkey_interrupt(int irq, void *dev_id)
} }
input_sync(input); 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; return IRQ_HANDLED;
} }
@ -229,14 +238,10 @@ static int mpr_touchkey_probe(struct i2c_client *client,
int vdd_uv; int vdd_uv;
struct mpr121_touchkey *mpr121; struct mpr121_touchkey *mpr121;
struct input_dev *input_dev; struct input_dev *input_dev;
u32 poll_interval = 0;
int error; int error;
int i; int i;
if (!client->irq) {
dev_err(dev, "irq number should not be zero\n");
return -EINVAL;
}
vdd_supply = mpr121_vdd_supply_init(dev); vdd_supply = mpr121_vdd_supply_init(dev);
if (IS_ERR(vdd_supply)) if (IS_ERR(vdd_supply))
return PTR_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")) if (device_property_read_bool(dev, "autorepeat"))
__set_bit(EV_REP, input_dev->evbit); __set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, mpr121);
input_dev->keycode = mpr121->keycodes; input_dev->keycode = mpr121->keycodes;
input_dev->keycodesize = sizeof(mpr121->keycodes[0]); input_dev->keycodesize = sizeof(mpr121->keycodes[0]);
@ -288,13 +294,40 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return error; return error;
} }
error = devm_request_threaded_irq(dev, client->irq, NULL, device_property_read_u32(dev, "poll-interval", &poll_interval);
mpr_touchkey_interrupt,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, if (client->irq) {
dev->driver->name, mpr121); error = devm_request_threaded_irq(dev, client->irq, NULL,
if (error) { mpr_touchkey_interrupt,
dev_err(dev, "Failed to register interrupt\n"); IRQF_TRIGGER_FALLING |
return error; 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); error = input_register_device(input_dev);

View File

@ -100,7 +100,6 @@ config INPUT_ATMEL_CAPTOUCH
config INPUT_BMA150 config INPUT_BMA150
tristate "BMA150/SMB380 acceleration sensor support" tristate "BMA150/SMB380 acceleration sensor support"
depends on I2C depends on I2C
select INPUT_POLLDEV
help help
Say Y here if you have Bosch Sensortec's BMA150 or SMB380 Say Y here if you have Bosch Sensortec's BMA150 or SMB380
acceleration sensor hooked to an I2C bus. acceleration sensor hooked to an I2C bus.
@ -246,7 +245,6 @@ config INPUT_MC13783_PWRBUTTON
config INPUT_MMA8450 config INPUT_MMA8450
tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer" tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
depends on I2C depends on I2C
select INPUT_POLLDEV
help help
Say Y here if you want to support Freescale's MMA8450 Accelerometer Say Y here if you want to support Freescale's MMA8450 Accelerometer
through I2C interface. through I2C interface.
@ -257,7 +255,6 @@ config INPUT_MMA8450
config INPUT_APANEL config INPUT_APANEL
tristate "Fujitsu Lifebook Application Panel buttons" tristate "Fujitsu Lifebook Application Panel buttons"
depends on X86 && I2C && LEDS_CLASS depends on X86 && I2C && LEDS_CLASS
select INPUT_POLLDEV
select CHECK_SIGNATURE select CHECK_SIGNATURE
help help
Say Y here for support of the Application Panel buttons, used on Say Y here for support of the Application Panel buttons, used on
@ -291,7 +288,6 @@ config INPUT_GPIO_BEEPER
config INPUT_GPIO_DECODER config INPUT_GPIO_DECODER
tristate "Polled GPIO Decoder Input driver" tristate "Polled GPIO Decoder Input driver"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
select INPUT_POLLDEV
help help
Say Y here if you want driver to read status of multiple GPIO Say Y here if you want driver to read status of multiple GPIO
lines and report the encoded value as an absolute integer to lines and report the encoded value as an absolute integer to
@ -327,7 +323,6 @@ config INPUT_IXP4XX_BEEPER
config INPUT_COBALT_BTNS config INPUT_COBALT_BTNS
tristate "Cobalt button interface" tristate "Cobalt button interface"
depends on MIPS_COBALT depends on MIPS_COBALT
select INPUT_POLLDEV
help help
Say Y here if you want to support MIPS Cobalt button interface. Say Y here if you want to support MIPS Cobalt button interface.
@ -347,7 +342,6 @@ config INPUT_CPCAP_PWRBUTTON
config INPUT_WISTRON_BTNS config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface" tristate "x86 Wistron laptop button interface"
depends on X86_32 depends on X86_32
select INPUT_POLLDEV
select INPUT_SPARSEKMAP select INPUT_SPARSEKMAP
select NEW_LEDS select NEW_LEDS
select LEDS_CLASS select LEDS_CLASS
@ -410,13 +404,6 @@ config INPUT_KXTJ9
To compile this driver as a module, choose M here: the module will To compile this driver as a module, choose M here: the module will
be called kxtj9. 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 config INPUT_POWERMATE
tristate "Griffin PowerMate and Contour Jog support" tristate "Griffin PowerMate and Contour Jog support"
depends on USB_ARCH_HAS_HCD depends on USB_ARCH_HAS_HCD
@ -546,7 +533,6 @@ config INPUT_UINPUT
config INPUT_SGI_BTNS config INPUT_SGI_BTNS
tristate "SGI Indy/O2 volume button interface" tristate "SGI Indy/O2 volume button interface"
depends on SGI_IP22 || SGI_IP32 depends on SGI_IP22 || SGI_IP32
select INPUT_POLLDEV
help help
Say Y here if you want to support SGI Indy/O2 volume button interface. 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" tristate "Mikrotik Routerboard 532 button interface"
depends on MIKROTIK_RB532 depends on MIKROTIK_RB532
depends on GPIOLIB depends on GPIOLIB
select INPUT_POLLDEV
help help
Say Y here if you want support for the S1 button built into Say Y here if you want support for the S1 button built into
Mikrotik's Routerboard 532. Mikrotik's Routerboard 532.

View File

@ -17,7 +17,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/leds.h> #include <linux/leds.h>
@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX];
#define MAX_PANEL_KEYS 12 #define MAX_PANEL_KEYS 12
struct apanel { struct apanel {
struct input_polled_dev *ipdev; struct input_dev *idev;
struct i2c_client *client; struct i2c_client *client;
unsigned short keymap[MAX_PANEL_KEYS]; unsigned short keymap[MAX_PANEL_KEYS];
u16 nkeys; u16 nkeys;
struct led_classdev mail_led; 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) 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_report_key(input, keycode, 1);
input_sync(input); input_sync(input);
@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode)
* CD keys: * CD keys:
* Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800) * 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 apanel *ap = input_get_drvdata(idev);
struct input_dev *idev = ipdev->input;
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
s32 data; s32 data;
int i; 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); 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) ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL);
led_classdev_unregister(&ap->mail_led); if (!ap)
return -ENOMEM;
input_unregister_polled_device(ap->ipdev); idev = devm_input_allocate_device(&client->dev);
input_free_polled_device(ap->ipdev); 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; return 0;
} }
static void apanel_shutdown(struct i2c_client *client) 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[] = { static const struct i2c_device_id apanel_id[] = {
@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = {
.driver = { .driver = {
.name = APANEL, .name = APANEL,
}, },
.probe = &apanel_probe, .probe = apanel_probe,
.remove = &apanel_remove, .shutdown = apanel_shutdown,
.shutdown = &apanel_shutdown,
.id_table = apanel_id, .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" */ /* Scan the system ROM for the signature "FJKEYINF" */
static __init const void __iomem *bios_signature(const void __iomem *bios) static __init const void __iomem *bios_signature(const void __iomem *bios)
{ {

View File

@ -14,7 +14,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -123,7 +122,6 @@
struct bma150_data { struct bma150_data {
struct i2c_client *client; struct i2c_client *client;
struct input_polled_dev *input_polled;
struct input_dev *input; struct input_dev *input;
u8 mode; u8 mode;
}; };
@ -336,13 +334,16 @@ static irqreturn_t bma150_irq_thread(int irq, void *dev)
return IRQ_HANDLED; 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; int error;
error = pm_runtime_get_sync(&bma150->client->dev); error = pm_runtime_get_sync(&bma150->client->dev);
@ -362,44 +363,18 @@ static int bma150_open(struct bma150_data *bma150)
return 0; 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); pm_runtime_put_sync(&bma150->client->dev);
if (bma150->mode != BMA150_MODE_SLEEP) if (bma150->mode != BMA150_MODE_SLEEP)
bma150_set_mode(bma150, 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, static int bma150_initialize(struct bma150_data *bma150,
const struct bma150_cfg *cfg) const struct bma150_cfg *cfg)
{ {
int error; int error;
@ -439,84 +414,14 @@ static int bma150_initialize(struct bma150_data *bma150,
return bma150_set_mode(bma150, BMA150_MODE_SLEEP); 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, 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 = const struct bma150_platform_data *pdata =
dev_get_platdata(&client->dev); dev_get_platdata(&client->dev);
const struct bma150_cfg *cfg; const struct bma150_cfg *cfg;
struct bma150_data *bma150; struct bma150_data *bma150;
struct input_dev *idev;
int chip_id; int chip_id;
int error; int error;
@ -531,7 +436,7 @@ static int bma150_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL); bma150 = devm_kzalloc(&client->dev, sizeof(*bma150), GFP_KERNEL);
if (!bma150) if (!bma150)
return -ENOMEM; return -ENOMEM;
@ -544,7 +449,7 @@ static int bma150_probe(struct i2c_client *client,
dev_err(&client->dev, dev_err(&client->dev,
"IRQ GPIO conf. error %d, error %d\n", "IRQ GPIO conf. error %d, error %d\n",
client->irq, error); client->irq, error);
goto err_free_mem; return error;
} }
} }
cfg = &pdata->cfg; cfg = &pdata->cfg;
@ -554,14 +459,42 @@ static int bma150_probe(struct i2c_client *client,
error = bma150_initialize(bma150, cfg); error = bma150_initialize(bma150, cfg);
if (error) 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) { if (client->irq > 0) {
error = bma150_register_input_device(bma150); error = devm_request_threaded_irq(&client->dev, client->irq,
if (error)
goto err_free_mem;
error = request_threaded_irq(client->irq,
NULL, bma150_irq_thread, NULL, bma150_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
BMA150_DRIVER, bma150); BMA150_DRIVER, bma150);
@ -569,13 +502,8 @@ static int bma150_probe(struct i2c_client *client,
dev_err(&client->dev, dev_err(&client->dev,
"irq request failed %d, error %d\n", "irq request failed %d, error %d\n",
client->irq, error); client->irq, error);
input_unregister_device(bma150->input); return error;
goto err_free_mem;
} }
} else {
error = bma150_register_polled_device(bma150);
if (error)
goto err_free_mem;
} }
i2c_set_clientdata(client, bma150); i2c_set_clientdata(client, bma150);
@ -583,33 +511,16 @@ static int bma150_probe(struct i2c_client *client,
pm_runtime_enable(&client->dev); pm_runtime_enable(&client->dev);
return 0; return 0;
err_free_mem:
kfree(bma150);
return error;
} }
static int bma150_remove(struct i2c_client *client) static int bma150_remove(struct i2c_client *client)
{ {
struct bma150_data *bma150 = i2c_get_clientdata(client);
pm_runtime_disable(&client->dev); 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; return 0;
} }
#ifdef CONFIG_PM static int __maybe_unused bma150_suspend(struct device *dev)
static int bma150_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct bma150_data *bma150 = i2c_get_clientdata(client); 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); 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 i2c_client *client = to_i2c_client(dev);
struct bma150_data *bma150 = i2c_get_clientdata(client); struct bma150_data *bma150 = i2c_get_clientdata(client);
return bma150_set_mode(bma150, BMA150_MODE_NORMAL); return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
} }
#endif
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);

View File

@ -4,7 +4,8 @@
* *
* Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> * 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/ioport.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -26,16 +27,14 @@ static const unsigned short cobalt_map[] = {
}; };
struct buttons_dev { struct buttons_dev {
struct input_polled_dev *poll_dev;
unsigned short keymap[ARRAY_SIZE(cobalt_map)]; unsigned short keymap[ARRAY_SIZE(cobalt_map)];
int count[ARRAY_SIZE(cobalt_map)]; int count[ARRAY_SIZE(cobalt_map)];
void __iomem *reg; 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 buttons_dev *bdev = input_get_drvdata(input);
struct input_dev *input = dev->input;
uint32_t status; uint32_t status;
int i; int i;
@ -62,29 +61,33 @@ static void handle_buttons(struct input_polled_dev *dev)
static int cobalt_buttons_probe(struct platform_device *pdev) static int cobalt_buttons_probe(struct platform_device *pdev)
{ {
struct buttons_dev *bdev; struct buttons_dev *bdev;
struct input_polled_dev *poll_dev;
struct input_dev *input; struct input_dev *input;
struct resource *res; struct resource *res;
int error, i; int error, i;
bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
poll_dev = input_allocate_polled_device(); if (!bdev)
if (!bdev || !poll_dev) { return -ENOMEM;
error = -ENOMEM;
goto err_free_mem; 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)); memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap));
poll_dev->private = bdev; input = devm_input_allocate_device(&pdev->dev);
poll_dev->poll = handle_buttons; if (!input)
poll_dev->poll_interval = BUTTONS_POLL_INTERVAL; return -ENOMEM;
input_set_drvdata(input, bdev);
input = poll_dev->input;
input->name = "Cobalt buttons"; input->name = "Cobalt buttons";
input->phys = "cobalt/input0"; input->phys = "cobalt/input0";
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
input->keycode = bdev->keymap; input->keycode = bdev->keymap;
input->keycodemax = ARRAY_SIZE(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); __set_bit(bdev->keymap[i], input->keybit);
__clear_bit(KEY_RESERVED, 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; error = input_setup_polling(input, handle_buttons);
bdev->reg = ioremap(res->start, resource_size(res));
dev_set_drvdata(&pdev->dev, bdev);
error = input_register_polled_device(poll_dev);
if (error) if (error)
goto err_iounmap; return error;
return 0; input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
err_iounmap: error = input_register_device(input);
iounmap(bdev->reg); if (error)
err_free_mem: return error;
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);
return 0; return 0;
} }
@ -141,7 +121,6 @@ MODULE_ALIAS("platform:Cobalt buttons");
static struct platform_driver cobalt_buttons_driver = { static struct platform_driver cobalt_buttons_driver = {
.probe = cobalt_buttons_probe, .probe = cobalt_buttons_probe,
.remove = cobalt_buttons_remove,
.driver = { .driver = {
.name = "Cobalt buttons", .name = "Cobalt buttons",
}, },

View File

@ -17,14 +17,12 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
struct gpio_decoder { struct gpio_decoder {
struct input_polled_dev *poll_dev;
struct gpio_descs *input_gpios; struct gpio_descs *input_gpios;
struct device *dev; struct device *dev;
u32 axis; u32 axis;
@ -53,15 +51,15 @@ static int gpio_decoder_get_gpios_state(struct gpio_decoder *decoder)
return ret; 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; int state;
state = gpio_decoder_get_gpios_state(decoder); state = gpio_decoder_get_gpios_state(decoder);
if (state >= 0 && state != decoder->last_stable) { if (state >= 0 && state != decoder->last_stable) {
input_report_abs(poll_dev->input, decoder->axis, state); input_report_abs(input, decoder->axis, state);
input_sync(poll_dev->input); input_sync(input);
decoder->last_stable = state; decoder->last_stable = state;
} }
} }
@ -70,20 +68,23 @@ static int gpio_decoder_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct gpio_decoder *decoder; struct gpio_decoder *decoder;
struct input_polled_dev *poll_dev; struct input_dev *input;
u32 max; u32 max;
int err; int err;
decoder = devm_kzalloc(dev, sizeof(struct gpio_decoder), GFP_KERNEL); decoder = devm_kzalloc(dev, sizeof(*decoder), GFP_KERNEL);
if (!decoder) if (!decoder)
return -ENOMEM; return -ENOMEM;
decoder->dev = dev;
device_property_read_u32(dev, "linux,axis", &decoder->axis); device_property_read_u32(dev, "linux,axis", &decoder->axis);
decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN); decoder->input_gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN);
if (IS_ERR(decoder->input_gpios)) { if (IS_ERR(decoder->input_gpios)) {
dev_err(dev, "unable to acquire input gpios\n"); dev_err(dev, "unable to acquire input gpios\n");
return PTR_ERR(decoder->input_gpios); return PTR_ERR(decoder->input_gpios);
} }
if (decoder->input_gpios->ndescs < 2) { if (decoder->input_gpios->ndescs < 2) {
dev_err(dev, "not enough gpios found\n"); dev_err(dev, "not enough gpios found\n");
return -EINVAL; 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)) if (device_property_read_u32(dev, "decoder-max-value", &max))
max = (1U << decoder->input_gpios->ndescs) - 1; max = (1U << decoder->input_gpios->ndescs) - 1;
decoder->dev = dev; input = devm_input_allocate_device(dev);
poll_dev = devm_input_allocate_polled_device(decoder->dev); if (!input)
if (!poll_dev)
return -ENOMEM; return -ENOMEM;
poll_dev->private = decoder; input_set_drvdata(input, decoder);
poll_dev->poll = gpio_decoder_poll_gpios;
decoder->poll_dev = poll_dev;
poll_dev->input->name = pdev->name; input->name = pdev->name;
poll_dev->input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input_set_abs_params(poll_dev->input, decoder->axis, 0, max, 0, 0); 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) { 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; return err;
} }

View File

@ -53,28 +53,10 @@ MODULE_LICENSE("Dual BSD/GPL");
#define RTC_VERSION "1.10d" #define RTC_VERSION "1.10d"
static DEFINE_MUTEX(hp_sdc_rtc_mutex);
static unsigned long epoch = 2000; static unsigned long epoch = 2000;
static struct semaphore i8042tregs; 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, static void hp_sdc_rtc_isr (int irq, void *dev_id,
uint8_t status, uint8_t data) uint8_t status, uint8_t data)
{ {
@ -283,151 +265,6 @@ static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
return 0; 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) static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
{ {
#define YN(bit) ("no") #define YN(bit) ("no")
@ -507,182 +344,6 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
#undef NY #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) static int __init hp_sdc_rtc_init(void)
{ {
int ret; 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))) if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
return ret; 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); 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) static void __exit hp_sdc_rtc_exit(void)
{ {
remove_proc_entry ("driver/rtc", NULL); remove_proc_entry ("driver/rtc", NULL);
misc_deregister(&hp_sdc_rtc_dev);
hp_sdc_release_timer_irq(hp_sdc_rtc_isr); hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n"); printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
} }

View File

@ -11,7 +11,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/input/kxtj9.h> #include <linux/input/kxtj9.h>
#include <linux/input-polldev.h>
#define NAME "kxtj9" #define NAME "kxtj9"
#define G_MAX 8000 #define G_MAX 8000
@ -71,9 +70,6 @@ struct kxtj9_data {
struct i2c_client *client; struct i2c_client *client;
struct kxtj9_platform_data pdata; struct kxtj9_platform_data pdata;
struct input_dev *input_dev; struct input_dev *input_dev;
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
struct input_polled_dev *poll_dev;
#endif
unsigned int last_poll_interval; unsigned int last_poll_interval;
u8 shift; u8 shift;
u8 ctrl_reg1; u8 ctrl_reg1;
@ -282,50 +278,6 @@ static void kxtj9_input_close(struct input_dev *dev)
kxtj9_disable(tj9); 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 * 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 * 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 .attrs = kxtj9_attributes
}; };
static void kxtj9_poll(struct input_dev *input)
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
static void kxtj9_poll(struct input_polled_dev *dev)
{ {
struct kxtj9_data *tj9 = dev->private; struct kxtj9_data *tj9 = input_get_drvdata(input);
unsigned int poll_interval = dev->poll_interval; unsigned int poll_interval = input_get_poll_interval(input);
kxtj9_report_acceleration_data(tj9); 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) static int kxtj9_verify(struct kxtj9_data *tj9)
{ {
int retval; int retval;
@ -494,11 +386,12 @@ out:
} }
static int kxtj9_probe(struct i2c_client *client, 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 = const struct kxtj9_platform_data *pdata =
dev_get_platdata(&client->dev); dev_get_platdata(&client->dev);
struct kxtj9_data *tj9; struct kxtj9_data *tj9;
struct input_dev *input_dev;
int err; int err;
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
@ -512,7 +405,7 @@ static int kxtj9_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL); tj9 = devm_kzalloc(&client->dev, sizeof(*tj9), GFP_KERNEL);
if (!tj9) { if (!tj9) {
dev_err(&client->dev, dev_err(&client->dev,
"failed to allocate memory for module data\n"); "failed to allocate memory for module data\n");
@ -525,13 +418,17 @@ static int kxtj9_probe(struct i2c_client *client,
if (pdata->init) { if (pdata->init) {
err = pdata->init(); err = pdata->init();
if (err < 0) 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); err = kxtj9_verify(tj9);
if (err < 0) { if (err < 0) {
dev_err(&client->dev, "device not recognized\n"); dev_err(&client->dev, "device not recognized\n");
goto err_pdata_exit; return err;
} }
i2c_set_clientdata(client, tj9); 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->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
tj9->last_poll_interval = tj9->pdata.init_interval; 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 (client->irq) {
/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */ /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL; tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
tj9->ctrl_reg1 |= DRDYE; tj9->ctrl_reg1 |= DRDYE;
err = kxtj9_setup_input_device(tj9); err = devm_request_threaded_irq(&client->dev, client->irq,
if (err) NULL, kxtj9_isr,
goto err_pdata_exit; IRQF_TRIGGER_RISING |
IRQF_ONESHOT,
err = request_threaded_irq(client->irq, NULL, kxtj9_isr, "kxtj9-irq", tj9);
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"kxtj9-irq", tj9);
if (err) { if (err) {
dev_err(&client->dev, "request irq failed: %d\n", 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) { if (err) {
dev_err(&client->dev, "sysfs create failed: %d\n", 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; return 0;
} }
@ -647,7 +540,6 @@ static struct i2c_driver kxtj9_driver = {
.pm = &kxtj9_pm_ops, .pm = &kxtj9_pm_ops,
}, },
.probe = kxtj9_probe, .probe = kxtj9_probe,
.remove = kxtj9_remove,
.id_table = kxtj9_id, .id_table = kxtj9_id,
}; };

View File

@ -10,7 +10,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#define MMA8450_DRV_NAME "mma8450" #define MMA8450_DRV_NAME "mma8450"
@ -39,15 +39,8 @@
#define MMA8450_CTRL_REG1 0x38 #define MMA8450_CTRL_REG1 0x38
#define MMA8450_CTRL_REG2 0x39 #define MMA8450_CTRL_REG2 0x39
/* mma8450 status */ static int mma8450_read(struct i2c_client *c, unsigned int off)
struct mma8450 {
struct i2c_client *client;
struct input_polled_dev *idev;
};
static int mma8450_read(struct mma8450 *m, unsigned off)
{ {
struct i2c_client *c = m->client;
int ret; int ret;
ret = i2c_smbus_read_byte_data(c, off); ret = i2c_smbus_read_byte_data(c, off);
@ -59,9 +52,8 @@ static int mma8450_read(struct mma8450 *m, unsigned off)
return ret; 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; int error;
error = i2c_smbus_write_byte_data(c, off, v); 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; 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) u8 *buf, size_t size)
{ {
struct i2c_client *c = m->client;
int err; int err;
err = i2c_smbus_read_i2c_block_data(c, off, size, buf); 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; 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 x, y, z;
int ret; int ret;
u8 buf[6]; u8 buf[6];
ret = mma8450_read(m, MMA8450_STATUS); ret = mma8450_read(c, MMA8450_STATUS);
if (ret < 0) if (ret < 0)
return; return;
if (!(ret & MMA8450_STATUS_ZXYDR)) if (!(ret & MMA8450_STATUS_ZXYDR))
return; 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) if (ret < 0)
return; return;
@ -114,41 +105,42 @@ static void mma8450_poll(struct input_polled_dev *dev)
y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf); y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf);
z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf); z = ((int)(s8)buf[5] << 4) | (buf[4] & 0xf);
input_report_abs(dev->input, ABS_X, x); input_report_abs(input, ABS_X, x);
input_report_abs(dev->input, ABS_Y, y); input_report_abs(input, ABS_Y, y);
input_report_abs(dev->input, ABS_Z, z); input_report_abs(input, ABS_Z, z);
input_sync(dev->input); input_sync(input);
} }
/* Initialize the MMA8450 chip */ /* 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; int err;
/* enable all events from X/Y/Z, no FIFO */ /* 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) if (err)
return; return err;
/* /*
* Sleep mode poll rate - 50Hz * Sleep mode poll rate - 50Hz
* System output data rate - 400Hz * System output data rate - 400Hz
* Full scale selection - Active, +/- 2G * Full scale selection - Active, +/- 2G
*/ */
err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01); err = mma8450_write(c, MMA8450_CTRL_REG1, 0x01);
if (err < 0) if (err)
return; return err;
msleep(MODE_CHANGE_DELAY_MS); 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(c, MMA8450_CTRL_REG1, 0x00);
mma8450_write(m, MMA8450_CTRL_REG2, 0x01); 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, static int mma8450_probe(struct i2c_client *c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct input_polled_dev *idev; struct input_dev *input;
struct mma8450 *m;
int err; int err;
m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL); input = devm_input_allocate_device(&c->dev);
if (!m) if (!input)
return -ENOMEM; return -ENOMEM;
idev = devm_input_allocate_polled_device(&c->dev); input_set_drvdata(input, c);
if (!idev)
return -ENOMEM;
m->client = c; input->name = MMA8450_DRV_NAME;
m->idev = idev; input->id.bustype = BUS_I2C;
idev->private = m; input->open = mma8450_open;
idev->input->name = MMA8450_DRV_NAME; input->close = mma8450_close;
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;
__set_bit(EV_ABS, idev->input->evbit); input_set_abs_params(input, ABS_X, -2048, 2047, 32, 32);
input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32); input_set_abs_params(input, ABS_Y, -2048, 2047, 32, 32);
input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32); input_set_abs_params(input, ABS_Z, -2048, 2047, 32, 32);
input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32);
err = input_register_polled_device(idev); err = input_setup_polling(input, mma8450_poll);
if (err) { 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; return err;
} }

View File

@ -5,7 +5,7 @@
* Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org> * Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org>
*/ */
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/gpio.h> #include <linux/gpio.h>
@ -46,56 +46,42 @@ static bool rb532_button_pressed(void)
return !val; 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, input_report_key(input, RB532_BTN_KSYM, rb532_button_pressed());
rb532_button_pressed()); input_sync(input);
input_sync(poll_dev->input);
} }
static int rb532_button_probe(struct platform_device *pdev) static int rb532_button_probe(struct platform_device *pdev)
{ {
struct input_polled_dev *poll_dev; struct input_dev *input;
int error; int error;
poll_dev = input_allocate_polled_device(); input = devm_input_allocate_device(&pdev->dev);
if (!poll_dev) if (!input)
return -ENOMEM; return -ENOMEM;
poll_dev->poll = rb532_button_poll; input->name = "rb532 button";
poll_dev->poll_interval = RB532_BTN_RATE; input->phys = "rb532/button0";
input->id.bustype = BUS_HOST;
poll_dev->input->name = "rb532 button"; input_set_capability(input, EV_KEY, RB532_BTN_KSYM);
poll_dev->input->phys = "rb532/button0";
poll_dev->input->id.bustype = BUS_HOST;
poll_dev->input->dev.parent = &pdev->dev;
dev_set_drvdata(&pdev->dev, poll_dev); error = input_setup_polling(input, rb532_button_poll);
if (error)
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);
return error; return error;
}
return 0; input_set_poll_interval(input, RB532_BTN_RATE);
}
static int rb532_button_remove(struct platform_device *pdev) error = input_register_device(input);
{ if (error)
struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev); return error;
input_unregister_polled_device(poll_dev);
input_free_polled_device(poll_dev);
return 0; return 0;
} }
static struct platform_driver rb532_button_driver = { static struct platform_driver rb532_button_driver = {
.probe = rb532_button_probe, .probe = rb532_button_probe,
.remove = rb532_button_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
}, },

View File

@ -4,7 +4,7 @@
* *
* Copyright (C) 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * Copyright (C) 2008 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*/ */
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -45,15 +45,13 @@ static const unsigned short sgi_map[] = {
}; };
struct buttons_dev { struct buttons_dev {
struct input_polled_dev *poll_dev;
unsigned short keymap[ARRAY_SIZE(sgi_map)]; unsigned short keymap[ARRAY_SIZE(sgi_map)];
int count[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 buttons_dev *bdev = input_get_drvdata(input);
struct input_dev *input = dev->input;
u8 status; u8 status;
int i; int i;
@ -80,28 +78,24 @@ static void handle_buttons(struct input_polled_dev *dev)
static int sgi_buttons_probe(struct platform_device *pdev) static int sgi_buttons_probe(struct platform_device *pdev)
{ {
struct buttons_dev *bdev; struct buttons_dev *bdev;
struct input_polled_dev *poll_dev;
struct input_dev *input; struct input_dev *input;
int error, i; int error, i;
bdev = kzalloc(sizeof(struct buttons_dev), GFP_KERNEL); bdev = devm_kzalloc(&pdev->dev, sizeof(*bdev), GFP_KERNEL);
poll_dev = input_allocate_polled_device(); if (!bdev)
if (!bdev || !poll_dev) { return -ENOMEM;
error = -ENOMEM;
goto err_free_mem; input = devm_input_allocate_device(&pdev->dev);
} if (!input)
return -ENOMEM;
memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap)); memcpy(bdev->keymap, sgi_map, sizeof(bdev->keymap));
poll_dev->private = bdev; input_set_drvdata(input, bdev);
poll_dev->poll = handle_buttons;
poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
input = poll_dev->input;
input->name = "SGI buttons"; input->name = "SGI buttons";
input->phys = "sgi/input0"; input->phys = "sgi/input0";
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
input->keycode = bdev->keymap; input->keycode = bdev->keymap;
input->keycodemax = ARRAY_SIZE(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); __set_bit(bdev->keymap[i], input->keybit);
__clear_bit(KEY_RESERVED, input->keybit); __clear_bit(KEY_RESERVED, input->keybit);
bdev->poll_dev = poll_dev; error = input_setup_polling(input, handle_buttons);
platform_set_drvdata(pdev, bdev);
error = input_register_polled_device(poll_dev);
if (error) if (error)
goto err_free_mem; return error;
return 0; input_set_poll_interval(input, BUTTONS_POLL_INTERVAL);
err_free_mem: error = input_register_device(input);
input_free_polled_device(poll_dev); if (error)
kfree(bdev); return error;
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);
return 0; return 0;
} }
static struct platform_driver sgi_buttons_driver = { static struct platform_driver sgi_buttons_driver = {
.probe = sgi_buttons_probe, .probe = sgi_buttons_probe,
.remove = sgi_buttons_remove,
.driver = { .driver = {
.name = "sgibtns", .name = "sgibtns",
}, },

View File

@ -8,7 +8,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/input/sparse-keymap.h> #include <linux/input/sparse-keymap.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
@ -1030,7 +1030,7 @@ static int __init select_keymap(void)
/* Input layer interface */ /* Input layer interface */
static struct input_polled_dev *wistron_idev; static struct input_dev *wistron_idev;
static unsigned long jiffies_last_press; static unsigned long jiffies_last_press;
static bool wifi_enabled; static bool wifi_enabled;
static bool bluetooth_enabled; static bool bluetooth_enabled;
@ -1114,7 +1114,7 @@ static inline void wistron_led_resume(void)
static void handle_key(u8 code) static void handle_key(u8 code)
{ {
const struct key_entry *key = const struct key_entry *key =
sparse_keymap_entry_from_scancode(wistron_idev->input, code); sparse_keymap_entry_from_scancode(wistron_idev, code);
if (key) { if (key) {
switch (key->type) { switch (key->type) {
@ -1133,14 +1133,14 @@ static void handle_key(u8 code)
break; break;
default: default:
sparse_keymap_report_entry(wistron_idev->input, sparse_keymap_report_entry(wistron_idev, key, 1, true);
key, 1, true);
break; break;
} }
jiffies_last_press = jiffies; jiffies_last_press = jiffies;
} else } else {
printk(KERN_NOTICE printk(KERN_NOTICE
"wistron_btns: Unknown key code %02X\n", code); "wistron_btns: Unknown key code %02X\n", code);
}
} }
static void poll_bios(bool discard) 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 */ /* Flush stale event queue */
poll_bios(true); 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); poll_bios(false);
/* Increase poll frequency if user is currently pressing keys (< 2s ago) */ /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
if (time_before(jiffies, jiffies_last_press + 2 * HZ)) if (time_before(jiffies, jiffies_last_press + 2 * HZ))
dev->poll_interval = POLL_INTERVAL_BURST; input_set_poll_interval(dev, POLL_INTERVAL_BURST);
else else
dev->poll_interval = POLL_INTERVAL_DEFAULT; input_set_poll_interval(dev, POLL_INTERVAL_DEFAULT);
} }
static int wistron_setup_keymap(struct input_dev *dev, 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) static int setup_input_dev(void)
{ {
struct input_dev *input_dev;
int error; int error;
wistron_idev = input_allocate_polled_device(); wistron_idev = input_allocate_device();
if (!wistron_idev) if (!wistron_idev)
return -ENOMEM; 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->open = wistron_flush;
wistron_idev->poll = wistron_poll;
wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
input_dev = wistron_idev->input; error = sparse_keymap_setup(wistron_idev, keymap, wistron_setup_keymap);
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);
if (error) if (error)
goto err_free_dev; 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) if (error)
goto err_free_dev; goto err_free_dev;
return 0; return 0;
err_free_dev: err_free_dev:
input_free_polled_device(wistron_idev); input_free_device(wistron_idev);
return error; return error;
} }
@ -1285,8 +1289,7 @@ static int wistron_probe(struct platform_device *dev)
static int wistron_remove(struct platform_device *dev) static int wistron_remove(struct platform_device *dev)
{ {
wistron_led_remove(); wistron_led_remove();
input_unregister_polled_device(wistron_idev); input_unregister_device(wistron_idev);
input_free_polled_device(wistron_idev);
bios_detach(); bios_detach();
return 0; return 0;

View File

@ -92,14 +92,14 @@ config MOUSE_PS2_SYNAPTICS_SMBUS
If unsure, say Y. If unsure, say Y.
config MOUSE_PS2_CYPRESS config MOUSE_PS2_CYPRESS
bool "Cypress PS/2 mouse protocol extension" if EXPERT bool "Cypress PS/2 mouse protocol extension" if EXPERT
default y default y
depends on MOUSE_PS2 depends on MOUSE_PS2
help help
Say Y here if you have a Cypress PS/2 Trackpad connected to Say Y here if you have a Cypress PS/2 Trackpad connected to
your system. your system.
If unsure, say Y. If unsure, say Y.
config MOUSE_PS2_LIFEBOOK config MOUSE_PS2_LIFEBOOK
bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT
@ -381,7 +381,6 @@ config MOUSE_VSXXXAA
config MOUSE_GPIO config MOUSE_GPIO
tristate "GPIO mouse" tristate "GPIO mouse"
depends on GPIOLIB || COMPILE_TEST depends on GPIOLIB || COMPILE_TEST
select INPUT_POLLDEV
help help
This driver simulates a mouse on GPIO lines of various CPUs (and some This driver simulates a mouse on GPIO lines of various CPUs (and some
other chips). other chips).

View File

@ -8,7 +8,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/of.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. * 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. * 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 gpio_mouse *gpio = input_get_drvdata(input);
struct input_dev *input = dev->input;
int x, y; int x, y;
if (gpio->bleft) if (gpio->bleft)
@ -71,18 +70,17 @@ static int gpio_mouse_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct gpio_mouse *gmouse; struct gpio_mouse *gmouse;
struct input_polled_dev *input_poll;
struct input_dev *input; struct input_dev *input;
int ret; int error;
gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL); gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
if (!gmouse) if (!gmouse)
return -ENOMEM; return -ENOMEM;
/* Assign some default scanning time */ /* Assign some default scanning time */
ret = device_property_read_u32(dev, "scan-interval-ms", error = device_property_read_u32(dev, "scan-interval-ms",
&gmouse->scan_ms); &gmouse->scan_ms);
if (ret || gmouse->scan_ms == 0) { if (error || gmouse->scan_ms == 0) {
dev_warn(dev, "invalid scan time, set to 50 ms\n"); dev_warn(dev, "invalid scan time, set to 50 ms\n");
gmouse->scan_ms = 50; gmouse->scan_ms = 50;
} }
@ -112,23 +110,14 @@ static int gpio_mouse_probe(struct platform_device *pdev)
if (IS_ERR(gmouse->bright)) if (IS_ERR(gmouse->bright))
return PTR_ERR(gmouse->bright); return PTR_ERR(gmouse->bright);
input_poll = devm_input_allocate_polled_device(dev); input = devm_input_allocate_device(dev);
if (!input_poll) { if (!input)
dev_err(dev, "not enough memory for input device\n");
return -ENOMEM; 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->name = pdev->name;
input->id.bustype = BUS_HOST; 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_X);
input_set_capability(input, EV_REL, REL_Y); input_set_capability(input, EV_REL, REL_Y);
@ -139,10 +128,16 @@ static int gpio_mouse_probe(struct platform_device *pdev)
if (gmouse->bright) if (gmouse->bright)
input_set_capability(input, EV_KEY, BTN_RIGHT); input_set_capability(input, EV_KEY, BTN_RIGHT);
ret = input_register_polled_device(input_poll); error = input_setup_polling(input, gpio_mouse_scan);
if (ret) { 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"); 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", dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",

View File

@ -172,6 +172,7 @@ static const char * const smbus_pnp_ids[] = {
"LEN0071", /* T480 */ "LEN0071", /* T480 */
"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */ "LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
"LEN0073", /* X1 Carbon G5 (Elantech) */ "LEN0073", /* X1 Carbon G5 (Elantech) */
"LEN0091", /* X1 Carbon 6 */
"LEN0092", /* X1 Carbon 6 */ "LEN0092", /* X1 Carbon 6 */
"LEN0093", /* T480 */ "LEN0093", /* T480 */
"LEN0096", /* X280 */ "LEN0096", /* X280 */

View File

@ -81,11 +81,6 @@ static const char * const rmi_f54_report_type_names[] = {
= "Full Raw Capacitance RX Offset Removed", = "Full Raw Capacitance RX Offset Removed",
}; };
struct rmi_f54_reports {
int start;
int size;
};
struct f54_data { struct f54_data {
struct rmi_function *fn; struct rmi_function *fn;
@ -98,7 +93,6 @@ struct f54_data {
enum rmi_f54_report_type report_type; enum rmi_f54_report_type report_type;
u8 *report_data; u8 *report_data;
int report_size; int report_size;
struct rmi_f54_reports standard_report[2];
bool is_busy; bool is_busy;
struct mutex status_mutex; struct mutex status_mutex;
@ -116,6 +110,7 @@ struct f54_data {
struct video_device vdev; struct video_device vdev;
struct vb2_queue queue; struct vb2_queue queue;
struct mutex lock; struct mutex lock;
u32 sequence;
int input; int input;
enum rmi_f54_report_type inputs[F54_MAX_REPORT_TYPE]; 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) 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); struct f54_data *f54 = vb2_get_drv_priv(vb->vb2_queue);
u16 *ptr; u16 *ptr;
enum vb2_buffer_state state; enum vb2_buffer_state state;
@ -298,6 +294,7 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
mutex_lock(&f54->status_mutex); mutex_lock(&f54->status_mutex);
vb2_set_plane_payload(vb, 0, 0);
reptype = rmi_f54_get_reptype(f54, f54->input); reptype = rmi_f54_get_reptype(f54, f54->input);
if (reptype == F54_REPORT_NONE) { if (reptype == F54_REPORT_NONE) {
state = VB2_BUF_STATE_ERROR; state = VB2_BUF_STATE_ERROR;
@ -344,14 +341,25 @@ static void rmi_f54_buffer_queue(struct vb2_buffer *vb)
data_done: data_done:
mutex_unlock(&f54->data_mutex); mutex_unlock(&f54->data_mutex);
done: done:
vb->timestamp = ktime_get_ns();
vbuf->field = V4L2_FIELD_NONE;
vbuf->sequence = f54->sequence++;
vb2_buffer_done(vb, state); vb2_buffer_done(vb, state);
mutex_unlock(&f54->status_mutex); 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 */ /* V4L2 structures */
static const struct vb2_ops rmi_f54_queue_ops = { static const struct vb2_ops rmi_f54_queue_ops = {
.queue_setup = rmi_f54_queue_setup, .queue_setup = rmi_f54_queue_setup,
.buf_queue = rmi_f54_buffer_queue, .buf_queue = rmi_f54_buffer_queue,
.stop_streaming = rmi_f54_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare, .wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish, .wait_finish = vb2_ops_wait_finish,
}; };
@ -363,7 +371,6 @@ static const struct vb2_queue rmi_f54_queue = {
.ops = &rmi_f54_queue_ops, .ops = &rmi_f54_queue_ops,
.mem_ops = &vb2_vmalloc_memops, .mem_ops = &vb2_vmalloc_memops,
.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC, .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
.min_buffers_needed = 1,
}; };
static int rmi_f54_vidioc_querycap(struct file *file, void *priv, 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 f54_data *f54 = container_of(work, struct f54_data, work.work);
struct rmi_function *fn = f54->fn; struct rmi_function *fn = f54->fn;
u8 fifo[2]; u8 fifo[2];
struct rmi_f54_reports *report;
int report_size; int report_size;
u8 command; u8 command;
u8 *data;
int error; int error;
data = f54->report_data;
report_size = rmi_f54_get_report_size(f54); report_size = rmi_f54_get_report_size(f54);
if (report_size == 0) { if (report_size == 0) {
dev_err(&fn->dev, "Bad report size, report type=%d\n", 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; error = -EINVAL;
goto error; /* retry won't help */ goto error; /* retry won't help */
} }
f54->standard_report[0].size = report_size;
report = f54->standard_report;
mutex_lock(&f54->data_mutex); 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"); rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n");
report_size = 0; fifo[0] = 0;
for (; report->size; report++) { fifo[1] = 0;
fifo[0] = report->start & 0xff; error = rmi_write_block(fn->rmi_dev,
fifo[1] = (report->start >> 8) & 0xff; fn->fd.data_base_addr + F54_FIFO_OFFSET,
error = rmi_write_block(fn->rmi_dev, fifo, sizeof(fifo));
fn->fd.data_base_addr + F54_FIFO_OFFSET, if (error) {
fifo, sizeof(fifo)); dev_err(&fn->dev, "Failed to set fifo start offset\n");
if (error) { goto abort;
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 + error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
F54_REPORT_DATA_OFFSET, data, F54_REPORT_DATA_OFFSET, f54->report_data,
report->size); report_size);
if (error) { if (error) {
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n", dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
__func__, report->size, error); __func__, report_size, error);
goto abort; goto abort;
}
data += report->size;
report_size += report->size;
} }
abort: abort:

View File

@ -39,16 +39,16 @@ config TABLET_USB_AIPTEK
module will be called aiptek. module will be called aiptek.
config TABLET_USB_GTCO config TABLET_USB_GTCO
tristate "GTCO CalComp/InterWrite USB Support" tristate "GTCO CalComp/InterWrite USB Support"
depends on USB && INPUT depends on USB && INPUT
help help
Say Y here if you want to use the USB version of the GTCO 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" CalComp/InterWrite Tablet. Make sure to say Y to "Mouse support"
(CONFIG_INPUT_MOUSEDEV) and/or "Event interface support" (CONFIG_INPUT_MOUSEDEV) and/or "Event interface support"
(CONFIG_INPUT_EVDEV) as well. (CONFIG_INPUT_EVDEV) as well.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called gtco. module will be called gtco.
config TABLET_USB_HANWANG config TABLET_USB_HANWANG
tristate "Hanwang Art Master III tablet support (USB)" tristate "Hanwang Art Master III tablet support (USB)"

View File

@ -633,7 +633,7 @@ config TOUCHSCREEN_HP600
depends on SH_HP6XX && SH_ADC depends on SH_HP6XX && SH_ADC
help help
Say Y here if you have a HP Jornada 620/660/680/690 and want to 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 To compile this driver as a module, choose M here: the
module will be called hp680_ts_input. module will be called hp680_ts_input.
@ -700,7 +700,6 @@ config TOUCHSCREEN_EDT_FT5X06
config TOUCHSCREEN_RASPBERRYPI_FW config TOUCHSCREEN_RASPBERRYPI_FW
tristate "Raspberry Pi's firmware base touch screen support" tristate "Raspberry Pi's firmware base touch screen support"
depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST) depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
select INPUT_POLLDEV
help help
Say Y here if you have the official Raspberry Pi 7 inch screen on Say Y here if you have the official Raspberry Pi 7 inch screen on
your system. your system.
@ -1038,7 +1037,6 @@ config TOUCHSCREEN_TS4800
depends on HAS_IOMEM && OF depends on HAS_IOMEM && OF
depends on SOC_IMX51 || COMPILE_TEST depends on SOC_IMX51 || COMPILE_TEST
select MFD_SYSCON select MFD_SYSCON
select INPUT_POLLDEV
help help
Say Y here if you have a touchscreen on a TS-4800 board. 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" tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
depends on USB && MEDIA_USB_SUPPORT && HAS_DMA depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
depends on VIDEO_V4L2 depends on VIDEO_V4L2
select INPUT_POLLDEV
select VIDEOBUF2_DMA_SG select VIDEOBUF2_DMA_SG
help help
Say Y here if you want support for the Samsung SUR40 touchscreen Say Y here if you want support for the Samsung SUR40 touchscreen
@ -1246,7 +1243,6 @@ config TOUCHSCREEN_SX8654
config TOUCHSCREEN_TPS6507X config TOUCHSCREEN_TPS6507X
tristate "TPS6507x based touchscreens" tristate "TPS6507x based touchscreens"
depends on I2C depends on I2C
select INPUT_POLLDEV
help help
Say Y here if you have a TPS6507x based touchscreen Say Y here if you have a TPS6507x based touchscreen
controller. controller.

View File

@ -13,7 +13,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.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_X 4095
#define AR1021_MAX_Y 4095 #define AR1021_MAX_Y 4095
@ -25,7 +25,7 @@
struct ar1021_i2c { struct ar1021_i2c {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; 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) static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id)

View File

@ -3156,6 +3156,8 @@ static int __maybe_unused mxt_suspend(struct device *dev)
mutex_unlock(&input_dev->mutex); mutex_unlock(&input_dev->mutex);
disable_irq(data->irq);
return 0; return 0;
} }
@ -3168,6 +3170,8 @@ static int __maybe_unused mxt_resume(struct device *dev)
if (!input_dev) if (!input_dev)
return 0; return 0;
enable_irq(data->irq);
mutex_lock(&input_dev->mutex); mutex_lock(&input_dev->mutex);
if (input_dev->users) if (input_dev->users)

View File

@ -9,7 +9,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/iio/consumer.h> #include <linux/iio/consumer.h>
#include <linux/iio/types.h> #include <linux/iio/types.h>

View File

@ -28,6 +28,7 @@
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/input/touchscreen.h> #include <linux/input/touchscreen.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/regulator/consumer.h>
#define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_THRESHOLD 0x00
#define WORK_REGISTER_REPORT_RATE 0x08 #define WORK_REGISTER_REPORT_RATE 0x08
@ -88,6 +89,7 @@ struct edt_ft5x06_ts_data {
struct touchscreen_properties prop; struct touchscreen_properties prop;
u16 num_x; u16 num_x;
u16 num_y; u16 num_y;
struct regulator *vcc;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct gpio_desc *wake_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, static int edt_ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) 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->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, tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
"reset", GPIOD_OUT_HIGH); "reset", GPIOD_OUT_HIGH);
if (IS_ERR(tsdata->reset_gpio)) { if (IS_ERR(tsdata->reset_gpio)) {

View File

@ -1,54 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-only // 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/i2c.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/input/touchscreen.h> #include <linux/input/touchscreen.h>
#include <linux/delay.h> #include <linux/interrupt.h>
#include <linux/workqueue.h> #include <linux/module.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define ILI210X_TOUCHES 2 #define ILI2XXX_POLL_PERIOD 20
#define ILI251X_TOUCHES 10
#define DEFAULT_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 */ /* Touchscreen commands */
#define REG_TOUCHDATA 0x10 #define REG_TOUCHDATA 0x10
#define REG_PANEL_INFO 0x20 #define REG_PANEL_INFO 0x20
#define REG_FIRMWARE_VERSION 0x40
#define REG_CALIBRATE 0xcc #define REG_CALIBRATE 0xcc
struct firmware_version { struct ili2xxx_chip {
u8 id; int (*read_reg)(struct i2c_client *client, u8 reg,
u8 major; void *buf, size_t len);
u8 minor; int (*get_touch_data)(struct i2c_client *client, u8 *data);
} __packed; bool (*parse_touch_data)(const u8 *data, unsigned int finger,
unsigned int *x, unsigned int *y);
enum ili2xxx_model { bool (*continue_polling)(const u8 *data, bool touch);
MODEL_ILI210X, unsigned int max_touches;
MODEL_ILI251X, unsigned int resolution;
bool has_calibrate_reg;
}; };
struct ili210x { struct ili210x {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
unsigned int poll_period;
struct delayed_work dwork;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct touchscreen_properties prop; struct touchscreen_properties prop;
enum ili2xxx_model model; const struct ili2xxx_chip *chip;
unsigned int max_touches; bool stop;
}; };
static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf, static int ili210x_read_reg(struct i2c_client *client,
size_t len) u8 reg, void *buf, size_t len)
{ {
struct ili210x *priv = i2c_get_clientdata(client); struct i2c_msg msg[] = {
struct i2c_msg msg[2] = {
{ {
.addr = client->addr, .addr = client->addr,
.flags = 0, .flags = 0,
@ -62,53 +62,28 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
.buf = buf, .buf = buf,
} }
}; };
int error, ret;
if (priv->model == MODEL_ILI251X) { ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
if (i2c_transfer(client->adapter, msg, 1) != 1) { if (ret != ARRAY_SIZE(msg)) {
dev_err(&client->dev, "i2c transfer failed\n"); error = ret < 0 ? ret : -EIO;
return -EIO; dev_err(&client->dev, "%s failed: %d\n", __func__, error);
} return error;
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;
}
} }
return 0; 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 = { return ili210x_read_reg(client, REG_TOUCHDATA,
.addr = client->addr, data, ILI210X_DATA_SIZE);
.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;
} }
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 finger,
unsigned int *x, unsigned int *y) unsigned int *x, unsigned int *y)
{ {
if (finger >= ILI210X_TOUCHES)
return false;
if (touchdata[0] & BIT(finger)) if (touchdata[0] & BIT(finger))
return false; return false;
@ -118,95 +93,192 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
return true; 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 finger,
unsigned int *x, unsigned int *y) 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; return false;
*x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0); *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
if (!(*x & BIT(15))) /* Touch indication */ 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, &reg, 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; return false;
*x &= 0x3fff; *x = val & 0x3fff;
*y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2); *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
return true; 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) static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
{ {
struct input_dev *input = priv->input; struct input_dev *input = priv->input;
int i; int i;
bool contact = false, touch = false; bool contact = false, touch;
unsigned int x = 0, y = 0; unsigned int x = 0, y = 0;
for (i = 0; i < priv->max_touches; i++) { for (i = 0; i < priv->chip->max_touches; i++) {
if (priv->model == MODEL_ILI210X) { touch = priv->chip->parse_touch_data(touchdata, i, &x, &y);
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;
}
input_mt_slot(input, i); input_mt_slot(input, i);
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) {
if (!touch) touchscreen_report_pos(input, &priv->prop, x, y, true);
continue; contact = true;
touchscreen_report_pos(input, &priv->prop, x, y, }
true);
} }
input_mt_report_pointer_emulation(input, false); input_mt_report_pointer_emulation(input, false);
input_sync(input); input_sync(input);
if (priv->model == MODEL_ILI210X)
contact = touchdata[0] & 0xf3;
return contact; 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) static irqreturn_t ili210x_irq(int irq, void *irq_data)
{ {
struct ili210x *priv = 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; return IRQ_HANDLED;
} }
@ -242,8 +314,19 @@ static struct attribute *ili210x_attributes[] = {
NULL, 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 = { static const struct attribute_group ili210x_attr_group = {
.attrs = ili210x_attributes, .attrs = ili210x_attributes,
.is_visible = ili210x_calibrate_visible,
}; };
static void ili210x_power_down(void *data) 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); gpiod_set_value_cansleep(reset_gpio, 1);
} }
static void ili210x_cancel_work(void *data) static void ili210x_stop(void *data)
{ {
struct ili210x *priv = 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, 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; struct device *dev = &client->dev;
const struct ili2xxx_chip *chip;
struct ili210x *priv; struct ili210x *priv;
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct input_dev *input; struct input_dev *input;
struct firmware_version firmware;
enum ili2xxx_model model;
int error; int error;
unsigned int max_xy;
model = (enum ili2xxx_model)id->driver_data;
dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver"); 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) { if (client->irq <= 0) {
dev_err(dev, "No IRQ!\n"); dev_err(dev, "No IRQ!\n");
return -EINVAL; return -EINVAL;
@ -305,49 +395,39 @@ static int ili210x_i2c_probe(struct i2c_client *client,
priv->client = client; priv->client = client;
priv->input = input; priv->input = input;
priv->poll_period = DEFAULT_POLL_PERIOD;
INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
priv->reset_gpio = reset_gpio; priv->reset_gpio = reset_gpio;
priv->model = model; priv->chip = chip;
if (model == MODEL_ILI210X)
priv->max_touches = ILI210X_TOUCHES;
if (model == MODEL_ILI251X)
priv->max_touches = ILI251X_TOUCHES;
i2c_set_clientdata(client, priv); 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 */ /* Setup input device */
input->name = "ILI210x Touchscreen"; input->name = "ILI210x Touchscreen";
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input->dev.parent = dev;
/* Multi touch */ /* Multi touch */
input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); max_xy = (chip->resolution ?: SZ_64K) - 1;
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); 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); 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); error = input_mt_init_slots(input, priv->chip->max_touches,
if (error) INPUT_MT_DIRECT);
if (error) {
dev_err(dev, "Unable to set up slots, err: %d\n", error);
return error; return error;
}
error = devm_request_irq(dev, client->irq, ili210x_irq, 0, error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
client->name, priv); IRQF_ONESHOT, client->name, priv);
if (error) { if (error) {
dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
error); error);
return 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); error = devm_device_add_group(dev, &ili210x_attr_group);
if (error) { if (error) {
dev_err(dev, "Unable to create sysfs attributes, err: %d\n", 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; 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; 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[] = { static const struct i2c_device_id ili210x_i2c_id[] = {
{ "ili210x", MODEL_ILI210X }, { "ili210x", (long)&ili210x_chip },
{ "ili251x", MODEL_ILI251X }, { "ili2117", (long)&ili211x_chip },
{ "ili251x", (long)&ili251x_chip },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id); MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
static const struct of_device_id ili210x_dt_ids[] = { static const struct of_device_id ili210x_dt_ids[] = {
{ .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X }, { .compatible = "ilitek,ili210x", .data = &ili210x_chip },
{ .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X }, { .compatible = "ilitek,ili2117", .data = &ili211x_chip },
{ }, { .compatible = "ilitek,ili251x", .data = &ili251x_chip },
{ }
}; };
MODULE_DEVICE_TABLE(of, ili210x_dt_ids); MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
static struct i2c_driver ili210x_ts_driver = { static struct i2c_driver ili210x_ts_driver = {
.driver = { .driver = {
.name = "ili210x_i2c", .name = "ili210x_i2c",
.pm = &ili210x_i2c_pm,
.of_match_table = ili210x_dt_ids, .of_match_table = ili210x_dt_ids,
}, },
.id_table = ili210x_i2c_id, .id_table = ili210x_i2c_id,

View File

@ -446,8 +446,7 @@ static int mms114_probe(struct i2c_client *client,
data->client = client; data->client = client;
data->input_dev = input_dev; data->input_dev = input_dev;
/* FIXME: switch to device_get_match_data() when available */ match_data = device_get_match_data(&client->dev);
match_data = of_device_get_match_data(&client->dev);
if (!match_data) if (!match_data)
return -EINVAL; return -EINVAL;

View File

@ -5,22 +5,73 @@
* Copyright (C) 2010-2011 Pixcir, Inc. * Copyright (C) 2010-2011 Pixcir, Inc.
*/ */
#include <asm/unaligned.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/module.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/input/touchscreen.h> #include <linux/input/touchscreen.h>
#include <linux/gpio.h> #include <linux/interrupt.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_data/pixcir_i2c_ts.h> #include <linux/module.h>
#include <asm/unaligned.h> #include <linux/slab.h>
#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ #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 pixcir_i2c_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
@ -30,7 +81,6 @@ struct pixcir_i2c_ts_data {
struct gpio_desc *gpio_wake; struct gpio_desc *gpio_wake;
const struct pixcir_i2c_chip_data *chip; const struct pixcir_i2c_chip_data *chip;
struct touchscreen_properties prop; struct touchscreen_properties prop;
int max_fingers; /* Max fingers supported in this instance */
bool running; 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)); memset(report, 0, sizeof(struct pixcir_report_data));
i = chip->has_hw_ids ? 1 : 0; 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)) if (readsize > sizeof(rdbuf))
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; touch = rdbuf[0] & 0x7;
if (touch > tsdata->max_fingers) if (touch > tsdata->chip->max_fingers)
touch = tsdata->max_fingers; touch = tsdata->chip->max_fingers;
report->num_touches = touch; report->num_touches = touch;
bufptr = &rdbuf[2]; 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); ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
if (ret < 0) { 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); __func__, PIXCIR_REG_POWER_MODE, ret);
return 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); ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
if (ret < 0) { 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); __func__, PIXCIR_REG_POWER_MODE, ret);
return 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); ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) { 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); __func__, PIXCIR_REG_INT_MODE, ret);
return 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); ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) { 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); __func__, PIXCIR_REG_INT_MODE, ret);
return 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); ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) { 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); __func__, PIXCIR_REG_INT_MODE, ret);
return 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); ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) { 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); __func__, PIXCIR_REG_INT_MODE, ret);
return ret; return ret;
} }
@ -412,31 +462,9 @@ unlock:
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); 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, static int pixcir_i2c_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev);
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct pixcir_i2c_ts_data *tsdata; struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input; struct input_dev *input;
@ -446,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
if (!tsdata) if (!tsdata)
return -ENOMEM; return -ENOMEM;
if (pdata) { tsdata->chip = device_get_match_data(dev);
tsdata->chip = &pdata->chip; if (!tsdata->chip && id)
} else if (dev->of_node) { tsdata->chip = (const void *)id->driver_data;
error = pixcir_parse_dt(dev, tsdata); if (!tsdata->chip) {
if (error) dev_err(dev, "can't locate chip data\n");
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");
return -EINVAL; return -EINVAL;
} }
@ -475,30 +495,17 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input->open = pixcir_input_open; input->open = pixcir_input_open;
input->close = pixcir_input_close; input->close = pixcir_input_close;
input->dev.parent = dev;
if (pdata) { input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); touchscreen_parse_properties(input, true, &tsdata->prop);
} else { if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); dev_err(dev, "Touchscreen size is not specified\n");
touchscreen_parse_properties(input, true, &tsdata->prop); return -EINVAL;
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; error = input_mt_init_slots(input, 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,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) { if (error) {
dev_err(dev, "Error initializing Multi-Touch slots\n"); 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); tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
if (IS_ERR(tsdata->gpio_attb)) { if (IS_ERR(tsdata->gpio_attb)) {
error = PTR_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; return error;
} }
@ -518,7 +527,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(tsdata->gpio_reset)) { if (IS_ERR(tsdata->gpio_reset)) {
error = PTR_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; return error;
} }
@ -574,14 +585,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return 0; 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 = { static const struct pixcir_i2c_chip_data pixcir_ts_data = {
.max_fingers = 2, .max_fingers = 2,
/* no hw id support */ /* no hw id support */
@ -592,6 +595,14 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
.has_hw_ids = true, .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[] = { static const struct of_device_id pixcir_of_match[] = {
{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data }, { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data }, { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },

View File

@ -16,7 +16,6 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/input-polldev.h>
#include <linux/input/touchscreen.h> #include <linux/input/touchscreen.h>
#include <soc/bcm2835/raspberrypi-firmware.h> #include <soc/bcm2835/raspberrypi-firmware.h>
@ -34,7 +33,7 @@
struct rpi_ts { struct rpi_ts {
struct platform_device *pdev; struct platform_device *pdev;
struct input_polled_dev *poll_dev; struct input_dev *input;
struct touchscreen_properties prop; struct touchscreen_properties prop;
void __iomem *fw_regs_va; void __iomem *fw_regs_va;
@ -57,10 +56,9 @@ struct rpi_ts_regs {
} point[RPI_TS_MAX_SUPPORTED_POINTS]; } 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 = input_get_drvdata(input);
struct rpi_ts *ts = dev->private;
struct rpi_ts_regs regs; struct rpi_ts_regs regs;
int modified_ids = 0; int modified_ids = 0;
long released_ids; long released_ids;
@ -123,10 +121,9 @@ static int rpi_ts_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct input_polled_dev *poll_dev; struct input_dev *input;
struct device_node *fw_node; struct device_node *fw_node;
struct rpi_firmware *fw; struct rpi_firmware *fw;
struct input_dev *input;
struct rpi_ts *ts; struct rpi_ts *ts;
u32 touchbuf; u32 touchbuf;
int error; int error;
@ -160,7 +157,6 @@ static int rpi_ts_probe(struct platform_device *pdev)
return error; return error;
} }
touchbuf = (u32)ts->fw_regs_phys; touchbuf = (u32)ts->fw_regs_phys;
error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
&touchbuf, sizeof(touchbuf)); &touchbuf, sizeof(touchbuf));
@ -170,19 +166,17 @@ static int rpi_ts_probe(struct platform_device *pdev)
return error; return error;
} }
poll_dev = devm_input_allocate_polled_device(dev); input = devm_input_allocate_device(dev);
if (!poll_dev) { if (!input) {
dev_err(dev, "Failed to allocate input device\n"); dev_err(dev, "Failed to allocate input device\n");
return -ENOMEM; return -ENOMEM;
} }
ts->poll_dev = poll_dev;
input = poll_dev->input; ts->input = input;
input_set_drvdata(input, ts);
input->name = "raspberrypi-ts"; input->name = "raspberrypi-ts";
input->id.bustype = BUS_HOST; 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, input_set_abs_params(input, ABS_MT_POSITION_X, 0,
RPI_TS_DEFAULT_WIDTH, 0, 0); RPI_TS_DEFAULT_WIDTH, 0, 0);
@ -197,7 +191,15 @@ static int rpi_ts_probe(struct platform_device *pdev)
return error; 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) { if (error) {
dev_err(dev, "could not register input device, %d\n", error); dev_err(dev, "could not register input device, %d\n", error);
return error; return error;
@ -214,10 +216,10 @@ MODULE_DEVICE_TABLE(of, rpi_ts_match);
static struct platform_driver rpi_ts_driver = { static struct platform_driver rpi_ts_driver = {
.driver = { .driver = {
.name = "raspberrypi-ts", .name = "raspberrypi-ts",
.of_match_table = rpi_ts_match, .of_match_table = rpi_ts_match,
}, },
.probe = rpi_ts_probe, .probe = rpi_ts_probe,
}; };
module_platform_driver(rpi_ts_driver); module_platform_driver(rpi_ts_driver);

View File

@ -13,7 +13,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/gpio.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>

View File

@ -14,23 +14,19 @@
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pm_qos.h> #include <linux/pm_qos.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/input/touchscreen.h>
#define ST1232_TS_NAME "st1232-ts" #define ST1232_TS_NAME "st1232-ts"
#define ST1633_TS_NAME "st1633-ts" #define ST1633_TS_NAME "st1633-ts"
struct st1232_ts_finger { #define ST_TS_MAX_FINGERS 10
u16 x;
u16 y;
u8 t;
bool is_valid;
};
struct st_chip_info { struct st_chip_info {
bool have_z; bool have_z;
@ -50,81 +46,89 @@ struct st1232_ts_data {
const struct st_chip_info *chip_info; const struct st_chip_info *chip_info;
int read_buf_len; int read_buf_len;
u8 *read_buf; u8 *read_buf;
struct st1232_ts_finger *finger;
}; };
static int st1232_ts_read_data(struct st1232_ts_data *ts) 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_client *client = ts->client;
struct i2c_msg msg[2];
int error;
int i, y;
u8 start_reg = ts->chip_info->start_reg; 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 */ ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
msg[0].addr = client->addr; if (ret != ARRAY_SIZE(msg))
msg[0].flags = 0; return ret < 0 ? ret : -EIO;
msg[0].len = 1;
msg[0].buf = &start_reg;
msg[1].addr = ts->client->addr; return 0;
msg[1].flags = I2C_M_RD; }
msg[1].len = ts->read_buf_len;
msg[1].buf = buf;
error = i2c_transfer(client->adapter, msg, 2); static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
if (error < 0) {
return error; 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) { for (i = 0; i < ts->chip_info->max_fingers; i++) {
finger[i].is_valid = buf[i + y] >> 7; u8 *buf = &ts->read_buf[i * 4];
if (finger[i].is_valid) {
finger[i].x = ((buf[i + y] & 0x0070) << 4) | if (buf[0] & BIT(7)) {
buf[i + y + 1]; unsigned int x = ((buf[0] & 0x70) << 4) | buf[1];
finger[i].y = ((buf[i + y] & 0x0007) << 8) | unsigned int y = ((buf[0] & 0x07) << 8) | buf[2];
buf[i + y + 2];
touchscreen_set_mt_pos(&pos[n_contacts],
&ts->prop, x, y);
/* st1232 includes a z-axis / touch strength */ /* st1232 includes a z-axis / touch strength */
if (ts->chip_info->have_z) 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) static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
{ {
struct st1232_ts_data *ts = dev_id; struct st1232_ts_data *ts = dev_id;
struct st1232_ts_finger *finger = ts->finger; int count;
struct input_dev *input_dev = ts->input_dev; int error;
int count = 0;
int i, ret;
ret = st1232_ts_read_data(ts); error = st1232_ts_read_data(ts);
if (ret < 0) if (error)
goto end; goto out;
/* multi touch protocol */ count = st1232_ts_parse_and_report(ts);
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 */
if (!count) { if (!count) {
input_mt_sync(input_dev);
if (ts->low_latency_req.dev) { if (ts->low_latency_req.dev) {
dev_pm_qos_remove_request(&ts->low_latency_req); dev_pm_qos_remove_request(&ts->low_latency_req);
ts->low_latency_req.dev = NULL; 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); DEV_PM_QOS_RESUME_LATENCY, 100);
} }
/* SYN_REPORT */ out:
input_sync(input_dev);
end:
return IRQ_HANDLED; 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); 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 = { static const struct st_chip_info st1232_chip_info = {
.have_z = true, .have_z = true,
.max_x = 0x31f, /* 800 - 1 */ .max_x = 0x31f, /* 800 - 1 */
@ -172,7 +178,6 @@ static int st1232_ts_probe(struct i2c_client *client,
{ {
const struct st_chip_info *match; const struct st_chip_info *match;
struct st1232_ts_data *ts; struct st1232_ts_data *ts;
struct st1232_ts_finger *finger;
struct input_dev *input_dev; struct input_dev *input_dev;
int error; int error;
@ -199,11 +204,6 @@ static int st1232_ts_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
ts->chip_info = match; 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 */ /* allocate a buffer according to the number of registers to read */
ts->read_buf_len = ts->chip_info->max_fingers * 4; 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); 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->name = "st1232-touchscreen";
input_dev->id.bustype = BUS_I2C; 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) if (ts->chip_info->have_z)
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 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); 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, error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, st1232_ts_irq_handler, NULL, st1232_ts_irq_handler,
IRQF_ONESHOT, IRQF_ONESHOT,
@ -266,16 +275,6 @@ static int st1232_ts_probe(struct i2c_client *client,
} }
i2c_set_clientdata(client, ts); 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; 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 i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client); struct st1232_ts_data *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev)) { disable_irq(client->irq);
enable_irq_wake(client->irq);
} else { if (!device_may_wakeup(&client->dev))
disable_irq(client->irq);
st1232_ts_power(ts, false); st1232_ts_power(ts, false);
}
return 0; 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 i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client); struct st1232_ts_data *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev)) { if (!device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
} else {
st1232_ts_power(ts, true); st1232_ts_power(ts, true);
enable_irq(client->irq);
} enable_irq(client->irq);
return 0; return 0;
} }
@ -329,7 +324,6 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
static struct i2c_driver st1232_ts_driver = { static struct i2c_driver st1232_ts_driver = {
.probe = st1232_ts_probe, .probe = st1232_ts_probe,
.remove = st1232_ts_remove,
.id_table = st1232_ts_id, .id_table = st1232_ts_id,
.driver = { .driver = {
.name = ST1232_TS_NAME, .name = ST1232_TS_NAME,

View File

@ -27,7 +27,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/input-polldev.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/usb/input.h> #include <linux/usb/input.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
@ -206,7 +206,7 @@ struct sur40_state {
struct usb_device *usbdev; struct usb_device *usbdev;
struct device *dev; struct device *dev;
struct input_polled_dev *input; struct input_dev *input;
struct v4l2_device v4l2; struct v4l2_device v4l2;
struct video_device vdev; struct video_device vdev;
@ -370,6 +370,10 @@ static int sur40_init(struct sur40_state *dev)
goto error; goto error;
result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12); 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 * 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. */ /* 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"); dev_dbg(sur40->dev, "open\n");
sur40_init(sur40); return sur40_init(sur40);
} }
/* Disable device, polling has stopped. */ /* 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"); 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 */ /* 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 sur40_state *sur40 = input_get_drvdata(input);
struct input_dev *input = polldev->input;
int result, bulk_read, need_blobs, packet_blobs, i; int result, bulk_read, need_blobs, packet_blobs, i;
u32 uninitialized_var(packet_id); u32 uninitialized_var(packet_id);
@ -613,10 +616,9 @@ err_poll:
} }
/* Initialize input device parameters. */ /* 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); int error;
__set_bit(EV_ABS, input_dev->evbit);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, SENSOR_RES_X, 0, 0); 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_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
input_mt_init_slots(input_dev, MAX_CONTACTS, error = input_mt_init_slots(input_dev, MAX_CONTACTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 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. */ /* Check candidate USB interface. */
@ -649,7 +657,7 @@ static int sur40_probe(struct usb_interface *interface,
struct sur40_state *sur40; struct sur40_state *sur40;
struct usb_host_interface *iface_desc; struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct input_polled_dev *poll_dev; struct input_dev *input;
int error; int error;
/* Check if we really have the right interface. */ /* Check if we really have the right interface. */
@ -670,8 +678,8 @@ static int sur40_probe(struct usb_interface *interface,
if (!sur40) if (!sur40)
return -ENOMEM; return -ENOMEM;
poll_dev = input_allocate_polled_device(); input = input_allocate_device();
if (!poll_dev) { if (!input) {
error = -ENOMEM; error = -ENOMEM;
goto err_free_dev; goto err_free_dev;
} }
@ -681,26 +689,33 @@ static int sur40_probe(struct usb_interface *interface,
spin_lock_init(&sur40->qlock); spin_lock_init(&sur40->qlock);
mutex_init(&sur40->lock); 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 */ /* Set up regular input device structure */
sur40_input_setup(poll_dev->input); input->name = DRIVER_LONG;
usb_to_input_id(usbdev, &input->id);
poll_dev->input->name = DRIVER_LONG;
usb_to_input_id(usbdev, &poll_dev->input->id);
usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys)); usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
strlcat(sur40->phys, "/input0", sizeof(sur40->phys)); strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
poll_dev->input->phys = sur40->phys; input->phys = sur40->phys;
poll_dev->input->dev.parent = &interface->dev; 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->usbdev = usbdev;
sur40->dev = &interface->dev; sur40->dev = &interface->dev;
sur40->input = poll_dev; sur40->input = input;
/* use the bulk-in endpoint tested above */ /* use the bulk-in endpoint tested above */
sur40->bulk_in_size = usb_endpoint_maxp(endpoint); 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) { if (!sur40->bulk_in_buffer) {
dev_err(&interface->dev, "Unable to allocate input buffer."); dev_err(&interface->dev, "Unable to allocate input buffer.");
error = -ENOMEM; error = -ENOMEM;
goto err_free_polldev; goto err_free_input;
} }
/* register the polled input device */ /* register the polled input device */
error = input_register_polled_device(poll_dev); error = input_register_device(input);
if (error) { if (error) {
dev_err(&interface->dev, dev_err(&interface->dev,
"Unable to register polled input device."); "Unable to register polled input device.");
@ -796,8 +811,8 @@ err_unreg_v4l2:
v4l2_device_unregister(&sur40->v4l2); v4l2_device_unregister(&sur40->v4l2);
err_free_buffer: err_free_buffer:
kfree(sur40->bulk_in_buffer); kfree(sur40->bulk_in_buffer);
err_free_polldev: err_free_input:
input_free_polled_device(sur40->input); input_free_device(input);
err_free_dev: err_free_dev:
kfree(sur40); kfree(sur40);
@ -813,8 +828,7 @@ static void sur40_disconnect(struct usb_interface *interface)
video_unregister_device(&sur40->vdev); video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2); v4l2_device_unregister(&sur40->v4l2);
input_unregister_polled_device(sur40->input); input_unregister_device(sur40->input);
input_free_polled_device(sur40->input);
kfree(sur40->bulk_in_buffer); kfree(sur40->bulk_in_buffer);
kfree(sur40); kfree(sur40);

View File

@ -17,7 +17,6 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/tps6507x.h> #include <linux/mfd/tps6507x.h>
#include <linux/input/tps6507x-ts.h> #include <linux/input/tps6507x-ts.h>
@ -40,7 +39,7 @@ struct ts_event {
struct tps6507x_ts { struct tps6507x_ts {
struct device *dev; struct device *dev;
struct input_polled_dev *poll_dev; struct input_dev *input;
struct tps6507x_dev *mfd; struct tps6507x_dev *mfd;
char phys[32]; char phys[32];
struct ts_event tc; struct ts_event tc;
@ -148,10 +147,9 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
return ret; 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 tps6507x_ts *tsc = input_get_drvdata(input_dev);
struct input_dev *input_dev = poll_dev->input;
bool pendown; bool pendown;
s32 ret; s32 ret;
@ -205,7 +203,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
const struct tps6507x_board *tps_board; const struct tps6507x_board *tps_board;
const struct touchscreen_init_data *init_data; const struct touchscreen_init_data *init_data;
struct tps6507x_ts *tsc; struct tps6507x_ts *tsc;
struct input_polled_dev *poll_dev;
struct input_dev *input_dev; struct input_dev *input_dev;
int error; int error;
@ -240,23 +237,16 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
snprintf(tsc->phys, sizeof(tsc->phys), snprintf(tsc->phys, sizeof(tsc->phys),
"%s/input0", dev_name(tsc->dev)); "%s/input0", dev_name(tsc->dev));
poll_dev = devm_input_allocate_polled_device(&pdev->dev); input_dev = devm_input_allocate_device(&pdev->dev);
if (!poll_dev) { if (!input_dev) {
dev_err(tsc->dev, "Failed to allocate polled input device.\n"); dev_err(tsc->dev, "Failed to allocate polled input device.\n");
return -ENOMEM; return -ENOMEM;
} }
tsc->poll_dev = poll_dev; tsc->input = input_dev;
input_set_drvdata(input_dev, tsc);
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);
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_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_Y, 0, MAX_10BIT, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 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) if (error)
return 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) if (error)
return error; return error;

View File

@ -10,7 +10,6 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
@ -33,7 +32,7 @@
#define Y_OFFSET 0x2 #define Y_OFFSET 0x2
struct ts4800_ts { struct ts4800_ts {
struct input_polled_dev *poll_dev; struct input_dev *input;
struct device *dev; struct device *dev;
char phys[32]; char phys[32];
@ -46,22 +45,26 @@ struct ts4800_ts {
int debounce; 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; struct ts4800_ts *ts = input_get_drvdata(input_dev);
int ret; int error;
ts->pendown = false; ts->pendown = false;
ts->debounce = DEBOUNCE_COUNT; ts->debounce = DEBOUNCE_COUNT;
ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit); error = regmap_update_bits(ts->regmap, ts->reg, ts->bit, ts->bit);
if (ret) if (error) {
dev_warn(ts->dev, "Failed to enable touchscreen\n"); 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; int ret;
ret = regmap_update_bits(ts->regmap, ts->reg, ts->bit, 0); 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 = input_get_drvdata(input_dev);
struct ts4800_ts *ts = dev->private;
u16 last_x = readw(ts->base + X_OFFSET); u16 last_x = readw(ts->base + X_OFFSET);
u16 last_y = readw(ts->base + Y_OFFSET); u16 last_y = readw(ts->base + Y_OFFSET);
bool pendown = last_x & PENDOWN_MASK; 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) static int ts4800_ts_probe(struct platform_device *pdev)
{ {
struct input_polled_dev *poll_dev; struct input_dev *input_dev;
struct ts4800_ts *ts; struct ts4800_ts *ts;
int error; int error;
@ -162,32 +164,38 @@ static int ts4800_ts_probe(struct platform_device *pdev)
if (IS_ERR(ts->base)) if (IS_ERR(ts->base))
return PTR_ERR(ts->base); return PTR_ERR(ts->base);
poll_dev = devm_input_allocate_polled_device(&pdev->dev); input_dev = devm_input_allocate_device(&pdev->dev);
if (!poll_dev) if (!input_dev)
return -ENOMEM; return -ENOMEM;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&pdev->dev)); 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; ts->dev = &pdev->dev;
poll_dev->private = ts; input_set_drvdata(input_dev, 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;
poll_dev->input->name = "TS-4800 Touchscreen"; input_dev->name = "TS-4800 Touchscreen";
poll_dev->input->phys = ts->phys; input_dev->phys = ts->phys;
input_set_capability(poll_dev->input, EV_KEY, BTN_TOUCH); input_dev->open = ts4800_ts_open;
input_set_abs_params(poll_dev->input, ABS_X, 0, MAX_12BIT, 0, 0); input_dev->close = ts4800_ts_close;
input_set_abs_params(poll_dev->input, ABS_Y, 0, MAX_12BIT, 0, 0);
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) { if (error) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Unabled to register polled input device (%d)\n", "Unable to register input device: %d\n", error);
error);
return error; return error;
} }

View File

@ -12,7 +12,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/gpio.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define WACOM_CMD_QUERY0 0x04 #define WACOM_CMD_QUERY0 0x04

View File

@ -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_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_min_poll_interval(struct input_dev *dev, unsigned int interval);
void input_set_max_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 *); int __must_check input_register_handler(struct input_handler *);
void input_unregister_handler(struct input_handler *); void input_unregister_handler(struct input_handler *);

View File

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