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:
- timeout-sec: contains the watchdog timeout in seconds.
SCU key bindings based on SCU Message Protocol
------------------------------------------------------------
Required properties:
- compatible: should be:
"fsl,imx8qxp-sc-key"
followed by "fsl,imx-sc-key";
- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
Example (imx8qxp):
-------------
aliases {
@ -220,6 +229,11 @@ firmware {
compatible = "fsl,imx8qxp-sc-rtc";
};
scu_key: scu-key {
compatible = "fsl,imx8qxp-sc-key", "fsl,imx-sc-key";
linux,keycodes = <KEY_POWER>;
};
watchdog {
compatible = "fsl,imx8qxp-sc-wdt", "fsl,imx-sc-wdt";
timeout-sec = <60>;

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:
- compatible:
ilitek,ili210x for ILI210x
ilitek,ili2117 for ILI2117
ilitek,ili251x for ILI251x
- 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:
- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
- linux,keycodes: See Documentation/devicetree/bindings/input/input.yaml
Optional Properties:
- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
- mediatek,long-press-mode: Long press key shutdown setting, 1 for
pwrkey only, 2 for pwrkey/homekey together, others for disabled.
- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt
- power-off-time-sec: See Documentation/devicetree/bindings/input/input.yaml
Example:

View File

@ -15,7 +15,7 @@ Optional properties:
- st,onkey-pu-inactive: onkey pull up is not active
- power-off-time-sec: Duration in seconds which the key should be kept
pressed for device to power off automatically (from 1 to 16 seconds).
see See Documentation/devicetree/bindings/input/keys.txt
see See Documentation/devicetree/bindings/input/input.yaml
Example:

View File

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

View File

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

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);
int input_get_poll_interval(struct input_dev *dev)
{
if (!dev->poller)
return -EINVAL;
return dev->poller->poll_interval;
}
EXPORT_SYMBOL(input_get_poll_interval);
/* SYSFS interface */
static ssize_t input_dev_get_poll_interval(struct device *dev,

View File

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

View File

@ -22,7 +22,6 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
@ -60,7 +59,7 @@ static const u8 PSX_CMD_ENABLE_MOTOR[] = {
struct psxpad {
struct spi_device *spi;
struct input_polled_dev *pdev;
struct input_dev *idev;
char phys[0x20];
bool motor1enable;
bool motor2enable;
@ -140,8 +139,7 @@ static void psxpad_set_motor_level(struct psxpad *pad,
static int psxpad_spi_play_effect(struct input_dev *idev,
void *data, struct ff_effect *effect)
{
struct input_polled_dev *pdev = input_get_drvdata(idev);
struct psxpad *pad = pdev->private;
struct psxpad *pad = input_get_drvdata(idev);
switch (effect->type) {
case FF_RUMBLE:
@ -158,10 +156,9 @@ static int psxpad_spi_init_ff(struct psxpad *pad)
{
int err;
input_set_capability(pad->pdev->input, EV_FF, FF_RUMBLE);
input_set_capability(pad->idev, EV_FF, FF_RUMBLE);
err = input_ff_create_memless(pad->pdev->input, NULL,
psxpad_spi_play_effect);
err = input_ff_create_memless(pad->idev, NULL, psxpad_spi_play_effect);
if (err) {
dev_err(&pad->spi->dev,
"input_ff_create_memless() failed: %d\n", err);
@ -189,24 +186,25 @@ static inline int psxpad_spi_init_ff(struct psxpad *pad)
}
#endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
static void psxpad_spi_poll_open(struct input_polled_dev *pdev)
static int psxpad_spi_poll_open(struct input_dev *input)
{
struct psxpad *pad = pdev->private;
struct psxpad *pad = input_get_drvdata(input);
pm_runtime_get_sync(&pad->spi->dev);
return 0;
}
static void psxpad_spi_poll_close(struct input_polled_dev *pdev)
static void psxpad_spi_poll_close(struct input_dev *input)
{
struct psxpad *pad = pdev->private;
struct psxpad *pad = input_get_drvdata(input);
pm_runtime_put_sync(&pad->spi->dev);
}
static void psxpad_spi_poll(struct input_polled_dev *pdev)
static void psxpad_spi_poll(struct input_dev *input)
{
struct psxpad *pad = pdev->private;
struct input_dev *input = pdev->input;
struct psxpad *pad = input_get_drvdata(input);
u8 b_rsp3, b_rsp4;
int err;
@ -284,7 +282,6 @@ static void psxpad_spi_poll(struct input_polled_dev *pdev)
static int psxpad_spi_probe(struct spi_device *spi)
{
struct psxpad *pad;
struct input_polled_dev *pdev;
struct input_dev *idev;
int err;
@ -292,31 +289,26 @@ static int psxpad_spi_probe(struct spi_device *spi)
if (!pad)
return -ENOMEM;
pdev = input_allocate_polled_device();
if (!pdev) {
idev = devm_input_allocate_device(&spi->dev);
if (!idev) {
dev_err(&spi->dev, "failed to allocate input device\n");
return -ENOMEM;
}
/* input poll device settings */
pad->pdev = pdev;
pad->idev = idev;
pad->spi = spi;
pdev->private = pad;
pdev->open = psxpad_spi_poll_open;
pdev->close = psxpad_spi_poll_close;
pdev->poll = psxpad_spi_poll;
/* poll interval is about 60fps */
pdev->poll_interval = 16;
pdev->poll_interval_min = 8;
pdev->poll_interval_max = 32;
/* input device settings */
idev = pdev->input;
input_set_drvdata(idev, pad);
idev->name = "PlayStation 1/2 joypad";
snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev));
idev->id.bustype = BUS_SPI;
idev->open = psxpad_spi_poll_open;
idev->close = psxpad_spi_poll_close;
/* key/value map settings */
input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0);
@ -354,11 +346,23 @@ static int psxpad_spi_probe(struct spi_device *spi)
/* pad settings */
psxpad_set_motor_level(pad, 0, 0);
err = input_setup_polling(idev, psxpad_spi_poll);
if (err) {
dev_err(&spi->dev, "failed to set up polling: %d\n", err);
return err;
}
/* poll interval is about 60fps */
input_set_poll_interval(idev, 16);
input_set_min_poll_interval(idev, 8);
input_set_max_poll_interval(idev, 32);
/* register input poll device */
err = input_register_polled_device(pdev);
err = input_register_device(idev);
if (err) {
dev_err(&spi->dev,
"failed to register input poll device: %d\n", err);
"failed to register input device: %d\n", err);
return err;
}

View File

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

View File

@ -29,6 +29,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o
obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o

View File

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

View File

@ -857,70 +857,35 @@ static void adp5589_report_switch_state(struct adp5589_kpad *kpad)
input_sync(kpad->input);
}
static int adp5589_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
{
struct adp5589_kpad *kpad;
struct i2c_client *client = kpad->client;
const struct adp5589_kpad_platform_data *pdata =
dev_get_platdata(&client->dev);
struct input_dev *input;
unsigned int revid;
int ret, i;
unsigned int i;
int error;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
return -EIO;
}
if (!pdata) {
dev_err(&client->dev, "no platform data?\n");
return -EINVAL;
}
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
if (!kpad)
return -ENOMEM;
switch (id->driver_data) {
case ADP5585_02:
kpad->support_row5 = true;
/* fall through */
case ADP5585_01:
kpad->is_adp5585 = true;
kpad->var = &const_adp5585;
break;
case ADP5589:
kpad->support_row5 = true;
kpad->var = &const_adp5589;
break;
}
if (!((pdata->keypad_en_mask & kpad->var->row_mask) &&
(pdata->keypad_en_mask >> kpad->var->col_shift)) ||
!pdata->keymap) {
dev_err(&client->dev, "no rows, cols or keymap from pdata\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
if (pdata->keymapsize != kpad->var->keymapsize) {
dev_err(&client->dev, "invalid keymapsize\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
if (!pdata->gpimap && pdata->gpimapsize) {
dev_err(&client->dev, "invalid gpimap from pdata\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
if (pdata->gpimapsize > kpad->var->gpimapsize_max) {
dev_err(&client->dev, "invalid gpimapsize\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
for (i = 0; i < pdata->gpimapsize; i++) {
@ -929,41 +894,27 @@ static int adp5589_probe(struct i2c_client *client,
if (pin < kpad->var->gpi_pin_base ||
pin > kpad->var->gpi_pin_end) {
dev_err(&client->dev, "invalid gpi pin data\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
if ((1 << (pin - kpad->var->gpi_pin_row_base)) &
pdata->keypad_en_mask) {
dev_err(&client->dev, "invalid gpi row/col data\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
}
if (!client->irq) {
dev_err(&client->dev, "no IRQ?\n");
error = -EINVAL;
goto err_free_mem;
return -EINVAL;
}
input = input_allocate_device();
if (!input) {
error = -ENOMEM;
goto err_free_mem;
}
if (!input)
return -ENOMEM;
kpad->client = client;
kpad->input = input;
ret = adp5589_read(client, ADP5589_5_ID);
if (ret < 0) {
error = ret;
goto err_free_input;
}
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
input->name = client->name;
input->phys = "adp5589-keys/input0";
input->dev.parent = &client->dev;
@ -1015,30 +966,99 @@ static int adp5589_probe(struct i2c_client *client,
goto err_unreg_dev;
}
device_init_wakeup(&client->dev, 1);
return 0;
err_unreg_dev:
input_unregister_device(input);
input = NULL;
err_free_input:
input_free_device(input);
return error;
}
static void adp5589_keypad_remove(struct adp5589_kpad *kpad)
{
if (kpad->input) {
free_irq(kpad->client->irq, kpad);
input_unregister_device(kpad->input);
}
}
static int adp5589_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct adp5589_kpad *kpad;
const struct adp5589_kpad_platform_data *pdata =
dev_get_platdata(&client->dev);
unsigned int revid;
int error, ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
return -EIO;
}
if (!pdata) {
dev_err(&client->dev, "no platform data?\n");
return -EINVAL;
}
kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
if (!kpad)
return -ENOMEM;
kpad->client = client;
switch (id->driver_data) {
case ADP5585_02:
kpad->support_row5 = true;
/* fall through */
case ADP5585_01:
kpad->is_adp5585 = true;
kpad->var = &const_adp5585;
break;
case ADP5589:
kpad->support_row5 = true;
kpad->var = &const_adp5589;
break;
}
ret = adp5589_read(client, ADP5589_5_ID);
if (ret < 0) {
error = ret;
goto err_free_mem;
}
revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK;
if (pdata->keymapsize) {
error = adp5589_keypad_add(kpad, revid);
if (error)
goto err_free_mem;
}
error = adp5589_setup(kpad);
if (error)
goto err_free_irq;
goto err_keypad_remove;
if (kpad->gpimapsize)
adp5589_report_switch_state(kpad);
error = adp5589_gpio_add(kpad);
if (error)
goto err_free_irq;
goto err_keypad_remove;
device_init_wakeup(&client->dev, 1);
i2c_set_clientdata(client, kpad);
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
return 0;
err_free_irq:
free_irq(client->irq, kpad);
err_unreg_dev:
input_unregister_device(input);
input = NULL;
err_free_input:
input_free_device(input);
err_keypad_remove:
adp5589_keypad_remove(kpad);
err_free_mem:
kfree(kpad);
@ -1050,8 +1070,7 @@ static int adp5589_remove(struct i2c_client *client)
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
free_irq(client->irq, kpad);
input_unregister_device(kpad->input);
adp5589_keypad_remove(kpad);
adp5589_gpio_remove(kpad);
kfree(kpad);
@ -1064,6 +1083,9 @@ static int adp5589_suspend(struct device *dev)
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client;
if (!kpad->input)
return 0;
disable_irq(client->irq);
if (device_may_wakeup(&client->dev))
@ -1077,6 +1099,9 @@ static int adp5589_resume(struct device *dev)
struct adp5589_kpad *kpad = dev_get_drvdata(dev);
struct i2c_client *client = kpad->client;
if (!kpad->input)
return 0;
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/input-polldev.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/leds.h>
@ -51,19 +51,28 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX];
#define MAX_PANEL_KEYS 12
struct apanel {
struct input_polled_dev *ipdev;
struct input_dev *idev;
struct i2c_client *client;
unsigned short keymap[MAX_PANEL_KEYS];
u16 nkeys;
u16 nkeys;
struct led_classdev mail_led;
};
static const unsigned short apanel_keymap[MAX_PANEL_KEYS] = {
[0] = KEY_MAIL,
[1] = KEY_WWW,
[2] = KEY_PROG2,
[3] = KEY_PROG1,
static int apanel_probe(struct i2c_client *, const struct i2c_device_id *);
[8] = KEY_FORWARD,
[9] = KEY_REWIND,
[10] = KEY_STOPCD,
[11] = KEY_PLAYPAUSE,
};
static void report_key(struct input_dev *input, unsigned keycode)
{
pr_debug(APANEL ": report key %#x\n", keycode);
dev_dbg(input->dev.parent, "report key %#x\n", keycode);
input_report_key(input, keycode, 1);
input_sync(input);
@ -79,10 +88,9 @@ static void report_key(struct input_dev *input, unsigned keycode)
* CD keys:
* Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800)
*/
static void apanel_poll(struct input_polled_dev *ipdev)
static void apanel_poll(struct input_dev *idev)
{
struct apanel *ap = ipdev->private;
struct input_dev *idev = ipdev->input;
struct apanel *ap = input_get_drvdata(idev);
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
s32 data;
int i;
@ -112,22 +120,76 @@ static int mail_led_set(struct led_classdev *led,
return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
}
static int apanel_remove(struct i2c_client *client)
static int apanel_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct apanel *ap = i2c_get_clientdata(client);
struct apanel *ap;
struct input_dev *idev;
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
int i, err;
if (device_chip[APANEL_DEV_LED] != CHIP_NONE)
led_classdev_unregister(&ap->mail_led);
ap = devm_kzalloc(&client->dev, sizeof(*ap), GFP_KERNEL);
if (!ap)
return -ENOMEM;
input_unregister_polled_device(ap->ipdev);
input_free_polled_device(ap->ipdev);
idev = devm_input_allocate_device(&client->dev);
if (!idev)
return -ENOMEM;
ap->idev = idev;
ap->client = client;
i2c_set_clientdata(client, ap);
err = i2c_smbus_write_word_data(client, cmd, 0);
if (err) {
dev_warn(&client->dev, "smbus write error %d\n", err);
return err;
}
input_set_drvdata(idev, ap);
idev->name = APANEL_NAME " buttons";
idev->phys = "apanel/input0";
idev->id.bustype = BUS_HOST;
memcpy(ap->keymap, apanel_keymap, sizeof(apanel_keymap));
idev->keycode = ap->keymap;
idev->keycodesize = sizeof(ap->keymap[0]);
idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4;
set_bit(EV_KEY, idev->evbit);
for (i = 0; i < idev->keycodemax; i++)
if (ap->keymap[i])
set_bit(ap->keymap[i], idev->keybit);
err = input_setup_polling(idev, apanel_poll);
if (err)
return err;
input_set_poll_interval(idev, POLL_INTERVAL_DEFAULT);
err = input_register_device(idev);
if (err)
return err;
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
ap->mail_led.name = "mail:blue";
ap->mail_led.brightness_set_blocking = mail_led_set;
err = devm_led_classdev_register(&client->dev, &ap->mail_led);
if (err)
return err;
}
return 0;
}
static void apanel_shutdown(struct i2c_client *client)
{
apanel_remove(client);
struct apanel *ap = i2c_get_clientdata(client);
if (device_chip[APANEL_DEV_LED] != CHIP_NONE)
led_set_brightness(&ap->mail_led, LED_OFF);
}
static const struct i2c_device_id apanel_id[] = {
@ -140,98 +202,11 @@ static struct i2c_driver apanel_driver = {
.driver = {
.name = APANEL,
},
.probe = &apanel_probe,
.remove = &apanel_remove,
.shutdown = &apanel_shutdown,
.probe = apanel_probe,
.shutdown = apanel_shutdown,
.id_table = apanel_id,
};
static struct apanel apanel = {
.keymap = {
[0] = KEY_MAIL,
[1] = KEY_WWW,
[2] = KEY_PROG2,
[3] = KEY_PROG1,
[8] = KEY_FORWARD,
[9] = KEY_REWIND,
[10] = KEY_STOPCD,
[11] = KEY_PLAYPAUSE,
},
.mail_led = {
.name = "mail:blue",
.brightness_set_blocking = mail_led_set,
},
};
/* NB: Only one panel on the i2c. */
static int apanel_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct apanel *ap;
struct input_polled_dev *ipdev;
struct input_dev *idev;
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
int i, err = -ENOMEM;
ap = &apanel;
ipdev = input_allocate_polled_device();
if (!ipdev)
goto out1;
ap->ipdev = ipdev;
ap->client = client;
i2c_set_clientdata(client, ap);
err = i2c_smbus_write_word_data(client, cmd, 0);
if (err) {
dev_warn(&client->dev, APANEL ": smbus write error %d\n",
err);
goto out3;
}
ipdev->poll = apanel_poll;
ipdev->poll_interval = POLL_INTERVAL_DEFAULT;
ipdev->private = ap;
idev = ipdev->input;
idev->name = APANEL_NAME " buttons";
idev->phys = "apanel/input0";
idev->id.bustype = BUS_HOST;
idev->dev.parent = &client->dev;
set_bit(EV_KEY, idev->evbit);
idev->keycode = ap->keymap;
idev->keycodesize = sizeof(ap->keymap[0]);
idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4;
for (i = 0; i < idev->keycodemax; i++)
if (ap->keymap[i])
set_bit(ap->keymap[i], idev->keybit);
err = input_register_polled_device(ipdev);
if (err)
goto out3;
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
err = led_classdev_register(&client->dev, &ap->mail_led);
if (err)
goto out4;
}
return 0;
out4:
input_unregister_polled_device(ipdev);
out3:
input_free_polled_device(ipdev);
out1:
return err;
}
/* Scan the system ROM for the signature "FJKEYINF" */
static __init const void __iomem *bios_signature(const void __iomem *bios)
{

View File

@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
@ -123,7 +122,6 @@
struct bma150_data {
struct i2c_client *client;
struct input_polled_dev *input_polled;
struct input_dev *input;
u8 mode;
};
@ -336,13 +334,16 @@ static irqreturn_t bma150_irq_thread(int irq, void *dev)
return IRQ_HANDLED;
}
static void bma150_poll(struct input_polled_dev *dev)
static void bma150_poll(struct input_dev *input)
{
bma150_report_xyz(dev->private);
struct bma150_data *bma150 = input_get_drvdata(input);
bma150_report_xyz(bma150);
}
static int bma150_open(struct bma150_data *bma150)
static int bma150_open(struct input_dev *input)
{
struct bma150_data *bma150 = input_get_drvdata(input);
int error;
error = pm_runtime_get_sync(&bma150->client->dev);
@ -362,44 +363,18 @@ static int bma150_open(struct bma150_data *bma150)
return 0;
}
static void bma150_close(struct bma150_data *bma150)
static void bma150_close(struct input_dev *input)
{
struct bma150_data *bma150 = input_get_drvdata(input);
pm_runtime_put_sync(&bma150->client->dev);
if (bma150->mode != BMA150_MODE_SLEEP)
bma150_set_mode(bma150, BMA150_MODE_SLEEP);
}
static int bma150_irq_open(struct input_dev *input)
{
struct bma150_data *bma150 = input_get_drvdata(input);
return bma150_open(bma150);
}
static void bma150_irq_close(struct input_dev *input)
{
struct bma150_data *bma150 = input_get_drvdata(input);
bma150_close(bma150);
}
static void bma150_poll_open(struct input_polled_dev *ipoll_dev)
{
struct bma150_data *bma150 = ipoll_dev->private;
bma150_open(bma150);
}
static void bma150_poll_close(struct input_polled_dev *ipoll_dev)
{
struct bma150_data *bma150 = ipoll_dev->private;
bma150_close(bma150);
}
static int bma150_initialize(struct bma150_data *bma150,
const struct bma150_cfg *cfg)
const struct bma150_cfg *cfg)
{
int error;
@ -439,84 +414,14 @@ static int bma150_initialize(struct bma150_data *bma150,
return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
}
static void bma150_init_input_device(struct bma150_data *bma150,
struct input_dev *idev)
{
idev->name = BMA150_DRIVER;
idev->phys = BMA150_DRIVER "/input0";
idev->id.bustype = BUS_I2C;
idev->dev.parent = &bma150->client->dev;
idev->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
}
static int bma150_register_input_device(struct bma150_data *bma150)
{
struct input_dev *idev;
int error;
idev = input_allocate_device();
if (!idev)
return -ENOMEM;
bma150_init_input_device(bma150, idev);
idev->open = bma150_irq_open;
idev->close = bma150_irq_close;
input_set_drvdata(idev, bma150);
bma150->input = idev;
error = input_register_device(idev);
if (error) {
input_free_device(idev);
return error;
}
return 0;
}
static int bma150_register_polled_device(struct bma150_data *bma150)
{
struct input_polled_dev *ipoll_dev;
int error;
ipoll_dev = input_allocate_polled_device();
if (!ipoll_dev)
return -ENOMEM;
ipoll_dev->private = bma150;
ipoll_dev->open = bma150_poll_open;
ipoll_dev->close = bma150_poll_close;
ipoll_dev->poll = bma150_poll;
ipoll_dev->poll_interval = BMA150_POLL_INTERVAL;
ipoll_dev->poll_interval_min = BMA150_POLL_MIN;
ipoll_dev->poll_interval_max = BMA150_POLL_MAX;
bma150_init_input_device(bma150, ipoll_dev->input);
bma150->input_polled = ipoll_dev;
bma150->input = ipoll_dev->input;
error = input_register_polled_device(ipoll_dev);
if (error) {
input_free_polled_device(ipoll_dev);
return error;
}
return 0;
}
static int bma150_probe(struct i2c_client *client,
const struct i2c_device_id *id)
const struct i2c_device_id *id)
{
const struct bma150_platform_data *pdata =
dev_get_platdata(&client->dev);
const struct bma150_cfg *cfg;
struct bma150_data *bma150;
struct input_dev *idev;
int chip_id;
int error;
@ -531,7 +436,7 @@ static int bma150_probe(struct i2c_client *client,
return -EINVAL;
}
bma150 = kzalloc(sizeof(struct bma150_data), GFP_KERNEL);
bma150 = devm_kzalloc(&client->dev, sizeof(*bma150), GFP_KERNEL);
if (!bma150)
return -ENOMEM;
@ -544,7 +449,7 @@ static int bma150_probe(struct i2c_client *client,
dev_err(&client->dev,
"IRQ GPIO conf. error %d, error %d\n",
client->irq, error);
goto err_free_mem;
return error;
}
}
cfg = &pdata->cfg;
@ -554,14 +459,42 @@ static int bma150_probe(struct i2c_client *client,
error = bma150_initialize(bma150, cfg);
if (error)
goto err_free_mem;
return error;
idev = devm_input_allocate_device(&bma150->client->dev);
if (!idev)
return -ENOMEM;
input_set_drvdata(idev, bma150);
bma150->input = idev;
idev->name = BMA150_DRIVER;
idev->phys = BMA150_DRIVER "/input0";
idev->id.bustype = BUS_I2C;
idev->open = bma150_open;
idev->close = bma150_close;
input_set_abs_params(idev, ABS_X, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
input_set_abs_params(idev, ABS_Y, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0);
if (client->irq <= 0) {
error = input_setup_polling(idev, bma150_poll);
if (error)
return error;
input_set_poll_interval(idev, BMA150_POLL_INTERVAL);
input_set_min_poll_interval(idev, BMA150_POLL_MIN);
input_set_max_poll_interval(idev, BMA150_POLL_MAX);
}
error = input_register_device(idev);
if (error)
return error;
if (client->irq > 0) {
error = bma150_register_input_device(bma150);
if (error)
goto err_free_mem;
error = request_threaded_irq(client->irq,
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, bma150_irq_thread,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
BMA150_DRIVER, bma150);
@ -569,13 +502,8 @@ static int bma150_probe(struct i2c_client *client,
dev_err(&client->dev,
"irq request failed %d, error %d\n",
client->irq, error);
input_unregister_device(bma150->input);
goto err_free_mem;
return error;
}
} else {
error = bma150_register_polled_device(bma150);
if (error)
goto err_free_mem;
}
i2c_set_clientdata(client, bma150);
@ -583,33 +511,16 @@ static int bma150_probe(struct i2c_client *client,
pm_runtime_enable(&client->dev);
return 0;
err_free_mem:
kfree(bma150);
return error;
}
static int bma150_remove(struct i2c_client *client)
{
struct bma150_data *bma150 = i2c_get_clientdata(client);
pm_runtime_disable(&client->dev);
if (client->irq > 0) {
free_irq(client->irq, bma150);
input_unregister_device(bma150->input);
} else {
input_unregister_polled_device(bma150->input_polled);
input_free_polled_device(bma150->input_polled);
}
kfree(bma150);
return 0;
}
#ifdef CONFIG_PM
static int bma150_suspend(struct device *dev)
static int __maybe_unused bma150_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct bma150_data *bma150 = i2c_get_clientdata(client);
@ -617,14 +528,13 @@ static int bma150_suspend(struct device *dev)
return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
}
static int bma150_resume(struct device *dev)
static int __maybe_unused bma150_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct bma150_data *bma150 = i2c_get_clientdata(client);
return bma150_set_mode(bma150, BMA150_MODE_NORMAL);
}
#endif
static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL);

View File

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

View File

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

View File

@ -53,28 +53,10 @@ MODULE_LICENSE("Dual BSD/GPL");
#define RTC_VERSION "1.10d"
static DEFINE_MUTEX(hp_sdc_rtc_mutex);
static unsigned long epoch = 2000;
static struct semaphore i8042tregs;
static hp_sdc_irqhook hp_sdc_rtc_isr;
static struct fasync_struct *hp_sdc_rtc_async_queue;
static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
static void hp_sdc_rtc_isr (int irq, void *dev_id,
uint8_t status, uint8_t data)
{
@ -283,151 +265,6 @@ static inline int hp_sdc_rtc_read_ct(struct timespec64 *res) {
return 0;
}
#if 0 /* not used yet */
/* Set the i8042 real-time clock */
static int hp_sdc_rtc_set_rt (struct timeval *setto)
{
uint32_t tenms;
unsigned int days;
hp_sdc_transaction t;
uint8_t tseq[11] = {
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
HP_SDC_CMD_SET_RTD, 2, 0, 0
};
t.endidx = 10;
if (0xffff < setto->tv_sec / 86400) return -1;
days = setto->tv_sec / 86400;
if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
if (days > 0xffff) return -1;
if (0xffffff < setto->tv_sec) return -1;
tenms = setto->tv_sec * 100;
if (0xffffff < setto->tv_usec / 10000) return -1;
tenms += setto->tv_usec / 10000;
if (tenms > 0xffffff) return -1;
tseq[3] = (uint8_t)(tenms & 0xff);
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
tseq[9] = (uint8_t)(days & 0xff);
tseq[10] = (uint8_t)((days >> 8) & 0xff);
t.seq = tseq;
if (hp_sdc_enqueue_transaction(&t)) return -1;
return 0;
}
/* Set the i8042 fast handshake timer */
static int hp_sdc_rtc_set_fhs (struct timeval *setto)
{
uint32_t tenms;
hp_sdc_transaction t;
uint8_t tseq[5] = {
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
HP_SDC_CMD_SET_FHS, 2, 0, 0
};
t.endidx = 4;
if (0xffff < setto->tv_sec) return -1;
tenms = setto->tv_sec * 100;
if (0xffff < setto->tv_usec / 10000) return -1;
tenms += setto->tv_usec / 10000;
if (tenms > 0xffff) return -1;
tseq[3] = (uint8_t)(tenms & 0xff);
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
t.seq = tseq;
if (hp_sdc_enqueue_transaction(&t)) return -1;
return 0;
}
/* Set the i8042 match timer (a.k.a. alarm) */
#define hp_sdc_rtc_set_mt (setto) \
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
/* Set the i8042 delay timer */
#define hp_sdc_rtc_set_dt (setto) \
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
/* Set the i8042 cycle timer (a.k.a. periodic) */
#define hp_sdc_rtc_set_ct (setto) \
hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
/* Set one of the i8042 3-byte wide timers */
static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
{
uint32_t tenms;
hp_sdc_transaction t;
uint8_t tseq[6] = {
HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
0, 3, 0, 0, 0
};
t.endidx = 6;
if (0xffffff < setto->tv_sec) return -1;
tenms = setto->tv_sec * 100;
if (0xffffff < setto->tv_usec / 10000) return -1;
tenms += setto->tv_usec / 10000;
if (tenms > 0xffffff) return -1;
tseq[1] = setcmd;
tseq[3] = (uint8_t)(tenms & 0xff);
tseq[4] = (uint8_t)((tenms >> 8) & 0xff);
tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
t.seq = tseq;
if (hp_sdc_enqueue_transaction(&t)) {
return -1;
}
return 0;
}
#endif
static ssize_t hp_sdc_rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) {
ssize_t retval;
if (count < sizeof(unsigned long))
return -EINVAL;
retval = put_user(68, (unsigned long __user *)buf);
return retval;
}
static __poll_t hp_sdc_rtc_poll(struct file *file, poll_table *wait)
{
unsigned long l;
l = 0;
if (l != 0)
return EPOLLIN | EPOLLRDNORM;
return 0;
}
static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
{
return 0;
}
static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
{
return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
}
static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
{
#define YN(bit) ("no")
@ -507,182 +344,6 @@ static int hp_sdc_rtc_proc_show(struct seq_file *m, void *v)
#undef NY
}
static int hp_sdc_rtc_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
#if 1
return -EINVAL;
#else
struct rtc_time wtime;
struct timeval ttime;
int use_wtime = 0;
/* This needs major work. */
switch (cmd) {
case RTC_AIE_OFF: /* Mask alarm int. enab. bit */
case RTC_AIE_ON: /* Allow alarm interrupts. */
case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
case RTC_PIE_ON: /* Allow periodic ints */
case RTC_UIE_ON: /* Allow ints for RTC updates. */
case RTC_UIE_OFF: /* Allow ints for RTC updates. */
{
/* We cannot mask individual user timers and we
cannot tell them apart when they occur, so it
would be disingenuous to succeed these IOCTLs */
return -EINVAL;
}
case RTC_ALM_READ: /* Read the present alarm time */
{
if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
wtime.tm_hour = ttime.tv_sec / 3600; ttime.tv_sec %= 3600;
wtime.tm_min = ttime.tv_sec / 60; ttime.tv_sec %= 60;
wtime.tm_sec = ttime.tv_sec;
break;
}
case RTC_IRQP_READ: /* Read the periodic IRQ rate. */
{
return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
}
case RTC_IRQP_SET: /* Set periodic IRQ rate. */
{
/*
* The max we can do is 100Hz.
*/
if ((arg < 1) || (arg > 100)) return -EINVAL;
ttime.tv_sec = 0;
ttime.tv_usec = 1000000 / arg;
if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
hp_sdc_rtc_freq = arg;
return 0;
}
case RTC_ALM_SET: /* Store a time into the alarm */
{
/*
* This expects a struct hp_sdc_rtc_time. Writing 0xff means
* "don't care" or "match all" for PC timers. The HP SDC
* does not support that perk, but it could be emulated fairly
* easily. Only the tm_hour, tm_min and tm_sec are used.
* We could do it with 10ms accuracy with the HP SDC, if the
* rtc interface left us a way to do that.
*/
struct hp_sdc_rtc_time alm_tm;
if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
sizeof(struct hp_sdc_rtc_time)))
return -EFAULT;
if (alm_tm.tm_hour > 23) return -EINVAL;
if (alm_tm.tm_min > 59) return -EINVAL;
if (alm_tm.tm_sec > 59) return -EINVAL;
ttime.sec = alm_tm.tm_hour * 3600 +
alm_tm.tm_min * 60 + alm_tm.tm_sec;
ttime.usec = 0;
if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
return 0;
}
case RTC_RD_TIME: /* Read the time/date from RTC */
{
if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
break;
}
case RTC_SET_TIME: /* Set the RTC */
{
struct rtc_time hp_sdc_rtc_tm;
unsigned char mon, day, hrs, min, sec, leap_yr;
unsigned int yrs;
if (!capable(CAP_SYS_TIME))
return -EACCES;
if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
sizeof(struct rtc_time)))
return -EFAULT;
yrs = hp_sdc_rtc_tm.tm_year + 1900;
mon = hp_sdc_rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
day = hp_sdc_rtc_tm.tm_mday;
hrs = hp_sdc_rtc_tm.tm_hour;
min = hp_sdc_rtc_tm.tm_min;
sec = hp_sdc_rtc_tm.tm_sec;
if (yrs < 1970)
return -EINVAL;
leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
if ((mon > 12) || (day == 0))
return -EINVAL;
if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
return -EINVAL;
if ((hrs >= 24) || (min >= 60) || (sec >= 60))
return -EINVAL;
if ((yrs -= eH) > 255) /* They are unsigned */
return -EINVAL;
return 0;
}
case RTC_EPOCH_READ: /* Read the epoch. */
{
return put_user (epoch, (unsigned long *)arg);
}
case RTC_EPOCH_SET: /* Set the epoch. */
{
/*
* There were no RTC clocks before 1900.
*/
if (arg < 1900)
return -EINVAL;
if (!capable(CAP_SYS_TIME))
return -EACCES;
epoch = arg;
return 0;
}
default:
return -EINVAL;
}
return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
#endif
}
static long hp_sdc_rtc_unlocked_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret;
mutex_lock(&hp_sdc_rtc_mutex);
ret = hp_sdc_rtc_ioctl(file, cmd, arg);
mutex_unlock(&hp_sdc_rtc_mutex);
return ret;
}
static const struct file_operations hp_sdc_rtc_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hp_sdc_rtc_read,
.poll = hp_sdc_rtc_poll,
.unlocked_ioctl = hp_sdc_rtc_unlocked_ioctl,
.open = hp_sdc_rtc_open,
.fasync = hp_sdc_rtc_fasync,
};
static struct miscdevice hp_sdc_rtc_dev = {
.minor = RTC_MINOR,
.name = "rtc_HIL",
.fops = &hp_sdc_rtc_fops
};
static int __init hp_sdc_rtc_init(void)
{
int ret;
@ -696,8 +357,6 @@ static int __init hp_sdc_rtc_init(void)
if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
return ret;
if (misc_register(&hp_sdc_rtc_dev) != 0)
printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
proc_create_single("driver/rtc", 0, NULL, hp_sdc_rtc_proc_show);
@ -710,7 +369,6 @@ static int __init hp_sdc_rtc_init(void)
static void __exit hp_sdc_rtc_exit(void)
{
remove_proc_entry ("driver/rtc", NULL);
misc_deregister(&hp_sdc_rtc_dev);
hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
}

View File

@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input/kxtj9.h>
#include <linux/input-polldev.h>
#define NAME "kxtj9"
#define G_MAX 8000
@ -71,9 +70,6 @@ struct kxtj9_data {
struct i2c_client *client;
struct kxtj9_platform_data pdata;
struct input_dev *input_dev;
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
struct input_polled_dev *poll_dev;
#endif
unsigned int last_poll_interval;
u8 shift;
u8 ctrl_reg1;
@ -282,50 +278,6 @@ static void kxtj9_input_close(struct input_dev *dev)
kxtj9_disable(tj9);
}
static void kxtj9_init_input_device(struct kxtj9_data *tj9,
struct input_dev *input_dev)
{
__set_bit(EV_ABS, input_dev->evbit);
input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
input_dev->name = "kxtj9_accel";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &tj9->client->dev;
}
static int kxtj9_setup_input_device(struct kxtj9_data *tj9)
{
struct input_dev *input_dev;
int err;
input_dev = input_allocate_device();
if (!input_dev) {
dev_err(&tj9->client->dev, "input device allocate failed\n");
return -ENOMEM;
}
tj9->input_dev = input_dev;
input_dev->open = kxtj9_input_open;
input_dev->close = kxtj9_input_close;
input_set_drvdata(input_dev, tj9);
kxtj9_init_input_device(tj9, input_dev);
err = input_register_device(tj9->input_dev);
if (err) {
dev_err(&tj9->client->dev,
"unable to register input polled device %s: %d\n",
tj9->input_dev->name, err);
input_free_device(tj9->input_dev);
return err;
}
return 0;
}
/*
* When IRQ mode is selected, we need to provide an interface to allow the user
* to change the output data rate of the part. For consistency, we are using
@ -391,12 +343,10 @@ static struct attribute_group kxtj9_attribute_group = {
.attrs = kxtj9_attributes
};
#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
static void kxtj9_poll(struct input_polled_dev *dev)
static void kxtj9_poll(struct input_dev *input)
{
struct kxtj9_data *tj9 = dev->private;
unsigned int poll_interval = dev->poll_interval;
struct kxtj9_data *tj9 = input_get_drvdata(input);
unsigned int poll_interval = input_get_poll_interval(input);
kxtj9_report_acceleration_data(tj9);
@ -406,72 +356,14 @@ static void kxtj9_poll(struct input_polled_dev *dev)
}
}
static void kxtj9_polled_input_open(struct input_polled_dev *dev)
static void kxtj9_platform_exit(void *data)
{
struct kxtj9_data *tj9 = dev->private;
struct kxtj9_data *tj9 = data;
kxtj9_enable(tj9);
if (tj9->pdata.exit)
tj9->pdata.exit();
}
static void kxtj9_polled_input_close(struct input_polled_dev *dev)
{
struct kxtj9_data *tj9 = dev->private;
kxtj9_disable(tj9);
}
static int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
{
int err;
struct input_polled_dev *poll_dev;
poll_dev = input_allocate_polled_device();
if (!poll_dev) {
dev_err(&tj9->client->dev,
"Failed to allocate polled device\n");
return -ENOMEM;
}
tj9->poll_dev = poll_dev;
tj9->input_dev = poll_dev->input;
poll_dev->private = tj9;
poll_dev->poll = kxtj9_poll;
poll_dev->open = kxtj9_polled_input_open;
poll_dev->close = kxtj9_polled_input_close;
kxtj9_init_input_device(tj9, poll_dev->input);
err = input_register_polled_device(poll_dev);
if (err) {
dev_err(&tj9->client->dev,
"Unable to register polled device, err=%d\n", err);
input_free_polled_device(poll_dev);
return err;
}
return 0;
}
static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
{
input_unregister_polled_device(tj9->poll_dev);
input_free_polled_device(tj9->poll_dev);
}
#else
static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9)
{
return -ENOSYS;
}
static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9)
{
}
#endif
static int kxtj9_verify(struct kxtj9_data *tj9)
{
int retval;
@ -494,11 +386,12 @@ out:
}
static int kxtj9_probe(struct i2c_client *client,
const struct i2c_device_id *id)
const struct i2c_device_id *id)
{
const struct kxtj9_platform_data *pdata =
dev_get_platdata(&client->dev);
struct kxtj9_data *tj9;
struct input_dev *input_dev;
int err;
if (!i2c_check_functionality(client->adapter,
@ -512,7 +405,7 @@ static int kxtj9_probe(struct i2c_client *client,
return -EINVAL;
}
tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
tj9 = devm_kzalloc(&client->dev, sizeof(*tj9), GFP_KERNEL);
if (!tj9) {
dev_err(&client->dev,
"failed to allocate memory for module data\n");
@ -525,13 +418,17 @@ static int kxtj9_probe(struct i2c_client *client,
if (pdata->init) {
err = pdata->init();
if (err < 0)
goto err_free_mem;
return err;
}
err = devm_add_action_or_reset(&client->dev, kxtj9_platform_exit, tj9);
if (err)
return err;
err = kxtj9_verify(tj9);
if (err < 0) {
dev_err(&client->dev, "device not recognized\n");
goto err_pdata_exit;
return err;
}
i2c_set_clientdata(client, tj9);
@ -539,66 +436,62 @@ static int kxtj9_probe(struct i2c_client *client,
tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range;
tj9->last_poll_interval = tj9->pdata.init_interval;
input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev) {
dev_err(&client->dev, "input device allocate failed\n");
return -ENOMEM;
}
input_set_drvdata(input_dev, tj9);
tj9->input_dev = input_dev;
input_dev->name = "kxtj9_accel";
input_dev->id.bustype = BUS_I2C;
input_dev->open = kxtj9_input_open;
input_dev->close = kxtj9_input_close;
input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
if (client->irq <= 0) {
err = input_setup_polling(input_dev, kxtj9_poll);
if (err)
return err;
}
err = input_register_device(input_dev);
if (err) {
dev_err(&client->dev,
"unable to register input polled device %s: %d\n",
input_dev->name, err);
return err;
}
if (client->irq) {
/* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */
tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL;
tj9->ctrl_reg1 |= DRDYE;
err = kxtj9_setup_input_device(tj9);
if (err)
goto err_pdata_exit;
err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"kxtj9-irq", tj9);
err = devm_request_threaded_irq(&client->dev, client->irq,
NULL, kxtj9_isr,
IRQF_TRIGGER_RISING |
IRQF_ONESHOT,
"kxtj9-irq", tj9);
if (err) {
dev_err(&client->dev, "request irq failed: %d\n", err);
goto err_destroy_input;
return err;
}
err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group);
err = devm_device_add_group(&client->dev,
&kxtj9_attribute_group);
if (err) {
dev_err(&client->dev, "sysfs create failed: %d\n", err);
goto err_free_irq;
return err;
}
} else {
err = kxtj9_setup_polled_device(tj9);
if (err)
goto err_pdata_exit;
}
return 0;
err_free_irq:
free_irq(client->irq, tj9);
err_destroy_input:
input_unregister_device(tj9->input_dev);
err_pdata_exit:
if (tj9->pdata.exit)
tj9->pdata.exit();
err_free_mem:
kfree(tj9);
return err;
}
static int kxtj9_remove(struct i2c_client *client)
{
struct kxtj9_data *tj9 = i2c_get_clientdata(client);
if (client->irq) {
sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group);
free_irq(client->irq, tj9);
input_unregister_device(tj9->input_dev);
} else {
kxtj9_teardown_polled_device(tj9);
}
if (tj9->pdata.exit)
tj9->pdata.exit();
kfree(tj9);
return 0;
}
@ -647,7 +540,6 @@ static struct i2c_driver kxtj9_driver = {
.pm = &kxtj9_pm_ops,
},
.probe = kxtj9_probe,
.remove = kxtj9_remove,
.id_table = kxtj9_id,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
#include <linux/input.h>
#include <linux/gpio/consumer.h>
#include <linux/property.h>
#include <linux/of.h>
@ -43,10 +43,9 @@ struct gpio_mouse {
* Timer function which is run every scan_ms ms when the device is opened.
* The dev input variable is set to the the input_dev pointer.
*/
static void gpio_mouse_scan(struct input_polled_dev *dev)
static void gpio_mouse_scan(struct input_dev *input)
{
struct gpio_mouse *gpio = dev->private;
struct input_dev *input = dev->input;
struct gpio_mouse *gpio = input_get_drvdata(input);
int x, y;
if (gpio->bleft)
@ -71,18 +70,17 @@ static int gpio_mouse_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct gpio_mouse *gmouse;
struct input_polled_dev *input_poll;
struct input_dev *input;
int ret;
int error;
gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL);
if (!gmouse)
return -ENOMEM;
/* Assign some default scanning time */
ret = device_property_read_u32(dev, "scan-interval-ms",
&gmouse->scan_ms);
if (ret || gmouse->scan_ms == 0) {
error = device_property_read_u32(dev, "scan-interval-ms",
&gmouse->scan_ms);
if (error || gmouse->scan_ms == 0) {
dev_warn(dev, "invalid scan time, set to 50 ms\n");
gmouse->scan_ms = 50;
}
@ -112,23 +110,14 @@ static int gpio_mouse_probe(struct platform_device *pdev)
if (IS_ERR(gmouse->bright))
return PTR_ERR(gmouse->bright);
input_poll = devm_input_allocate_polled_device(dev);
if (!input_poll) {
dev_err(dev, "not enough memory for input device\n");
input = devm_input_allocate_device(dev);
if (!input)
return -ENOMEM;
}
platform_set_drvdata(pdev, input_poll);
/* set input-polldev handlers */
input_poll->private = gmouse;
input_poll->poll = gpio_mouse_scan;
input_poll->poll_interval = gmouse->scan_ms;
input = input_poll->input;
input->name = pdev->name;
input->id.bustype = BUS_HOST;
input->dev.parent = &pdev->dev;
input_set_drvdata(input, gmouse);
input_set_capability(input, EV_REL, REL_X);
input_set_capability(input, EV_REL, REL_Y);
@ -139,10 +128,16 @@ static int gpio_mouse_probe(struct platform_device *pdev)
if (gmouse->bright)
input_set_capability(input, EV_KEY, BTN_RIGHT);
ret = input_register_polled_device(input_poll);
if (ret) {
error = input_setup_polling(input, gpio_mouse_scan);
if (error)
return error;
input_set_poll_interval(input, gmouse->scan_ms);
error = input_register_device(input);
if (error) {
dev_err(dev, "could not register input device\n");
return ret;
return error;
}
dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n",

View File

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

View File

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

View File

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

View File

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

View File

@ -13,7 +13,7 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#define AR1021_TOCUH_PKG_SIZE 5
#define AR1021_TOUCH_PKG_SIZE 5
#define AR1021_MAX_X 4095
#define AR1021_MAX_Y 4095
@ -25,7 +25,7 @@
struct ar1021_i2c {
struct i2c_client *client;
struct input_dev *input;
u8 data[AR1021_TOCUH_PKG_SIZE];
u8 data[AR1021_TOUCH_PKG_SIZE];
};
static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id)

View File

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

View File

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

View File

@ -28,6 +28,7 @@
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <asm/unaligned.h>
#include <linux/regulator/consumer.h>
#define WORK_REGISTER_THRESHOLD 0x00
#define WORK_REGISTER_REPORT_RATE 0x08
@ -88,6 +89,7 @@ struct edt_ft5x06_ts_data {
struct touchscreen_properties prop;
u16 num_x;
u16 num_y;
struct regulator *vcc;
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
@ -1036,6 +1038,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
static void edt_ft5x06_disable_regulator(void *arg)
{
struct edt_ft5x06_ts_data *data = arg;
regulator_disable(data->vcc);
}
static int edt_ft5x06_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -1064,6 +1073,27 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
tsdata->max_support_points = chip_data->max_support_points;
tsdata->vcc = devm_regulator_get(&client->dev, "vcc");
if (IS_ERR(tsdata->vcc)) {
error = PTR_ERR(tsdata->vcc);
if (error != -EPROBE_DEFER)
dev_err(&client->dev,
"failed to request regulator: %d\n", error);
return error;
}
error = regulator_enable(tsdata->vcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
return error;
}
error = devm_add_action_or_reset(&client->dev,
edt_ft5x06_disable_regulator,
tsdata);
if (error)
return error;
tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
"reset", GPIOD_OUT_HIGH);
if (IS_ERR(tsdata->reset_gpio)) {

View File

@ -1,54 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#define ILI210X_TOUCHES 2
#define ILI251X_TOUCHES 10
#define DEFAULT_POLL_PERIOD 20
#define ILI2XXX_POLL_PERIOD 20
#define ILI210X_DATA_SIZE 64
#define ILI211X_DATA_SIZE 43
#define ILI251X_DATA_SIZE1 31
#define ILI251X_DATA_SIZE2 20
/* Touchscreen commands */
#define REG_TOUCHDATA 0x10
#define REG_PANEL_INFO 0x20
#define REG_FIRMWARE_VERSION 0x40
#define REG_CALIBRATE 0xcc
struct firmware_version {
u8 id;
u8 major;
u8 minor;
} __packed;
enum ili2xxx_model {
MODEL_ILI210X,
MODEL_ILI251X,
struct ili2xxx_chip {
int (*read_reg)(struct i2c_client *client, u8 reg,
void *buf, size_t len);
int (*get_touch_data)(struct i2c_client *client, u8 *data);
bool (*parse_touch_data)(const u8 *data, unsigned int finger,
unsigned int *x, unsigned int *y);
bool (*continue_polling)(const u8 *data, bool touch);
unsigned int max_touches;
unsigned int resolution;
bool has_calibrate_reg;
};
struct ili210x {
struct i2c_client *client;
struct input_dev *input;
unsigned int poll_period;
struct delayed_work dwork;
struct gpio_desc *reset_gpio;
struct touchscreen_properties prop;
enum ili2xxx_model model;
unsigned int max_touches;
const struct ili2xxx_chip *chip;
bool stop;
};
static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
size_t len)
static int ili210x_read_reg(struct i2c_client *client,
u8 reg, void *buf, size_t len)
{
struct ili210x *priv = i2c_get_clientdata(client);
struct i2c_msg msg[2] = {
struct i2c_msg msg[] = {
{
.addr = client->addr,
.flags = 0,
@ -62,53 +62,28 @@ static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
.buf = buf,
}
};
int error, ret;
if (priv->model == MODEL_ILI251X) {
if (i2c_transfer(client->adapter, msg, 1) != 1) {
dev_err(&client->dev, "i2c transfer failed\n");
return -EIO;
}
usleep_range(5000, 5500);
if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
dev_err(&client->dev, "i2c transfer failed\n");
return -EIO;
}
} else {
if (i2c_transfer(client->adapter, msg, 2) != 2) {
dev_err(&client->dev, "i2c transfer failed\n");
return -EIO;
}
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
if (ret != ARRAY_SIZE(msg)) {
error = ret < 0 ? ret : -EIO;
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
return error;
}
return 0;
}
static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
static int ili210x_read_touch_data(struct i2c_client *client, u8 *data)
{
struct i2c_msg msg = {
.addr = client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
};
if (i2c_transfer(client->adapter, &msg, 1) != 1) {
dev_err(&client->dev, "i2c transfer failed\n");
return -EIO;
}
return 0;
return ili210x_read_reg(client, REG_TOUCHDATA,
data, ILI210X_DATA_SIZE);
}
static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
static bool ili210x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
unsigned int *x, unsigned int *y)
{
if (finger >= ILI210X_TOUCHES)
return false;
if (touchdata[0] & BIT(finger))
return false;
@ -118,95 +93,192 @@ static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
return true;
}
static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
static bool ili210x_check_continue_polling(const u8 *data, bool touch)
{
return data[0] & 0xf3;
}
static const struct ili2xxx_chip ili210x_chip = {
.read_reg = ili210x_read_reg,
.get_touch_data = ili210x_read_touch_data,
.parse_touch_data = ili210x_touchdata_to_coords,
.continue_polling = ili210x_check_continue_polling,
.max_touches = 2,
.has_calibrate_reg = true,
};
static int ili211x_read_touch_data(struct i2c_client *client, u8 *data)
{
s16 sum = 0;
int error;
int ret;
int i;
ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE);
if (ret != ILI211X_DATA_SIZE) {
error = ret < 0 ? ret : -EIO;
dev_err(&client->dev, "%s failed: %d\n", __func__, error);
return error;
}
/* This chip uses custom checksum at the end of data */
for (i = 0; i < ILI211X_DATA_SIZE - 1; i++)
sum = (sum + data[i]) & 0xff;
if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) {
dev_err(&client->dev,
"CRC error (crc=0x%02x expected=0x%02x)\n",
sum, data[ILI211X_DATA_SIZE - 1]);
return -EIO;
}
return 0;
}
static bool ili211x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
unsigned int *x, unsigned int *y)
{
if (finger >= ILI251X_TOUCHES)
u32 data;
data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0);
if (data == 0xffffffff) /* Finger up */
return false;
*x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
if (!(*x & BIT(15))) /* Touch indication */
*x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
touchdata[1 + (finger * 4) + 1];
*y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) |
touchdata[1 + (finger * 4) + 2];
return true;
}
static bool ili211x_decline_polling(const u8 *data, bool touch)
{
return false;
}
static const struct ili2xxx_chip ili211x_chip = {
.read_reg = ili210x_read_reg,
.get_touch_data = ili211x_read_touch_data,
.parse_touch_data = ili211x_touchdata_to_coords,
.continue_polling = ili211x_decline_polling,
.max_touches = 10,
.resolution = 2048,
};
static int ili251x_read_reg(struct i2c_client *client,
u8 reg, void *buf, size_t len)
{
int error;
int ret;
ret = i2c_master_send(client, &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;
*x &= 0x3fff;
*x = val & 0x3fff;
*y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
return true;
}
static bool ili251x_check_continue_polling(const u8 *data, bool touch)
{
return touch;
}
static const struct ili2xxx_chip ili251x_chip = {
.read_reg = ili251x_read_reg,
.get_touch_data = ili251x_read_touch_data,
.parse_touch_data = ili251x_touchdata_to_coords,
.continue_polling = ili251x_check_continue_polling,
.max_touches = 10,
.has_calibrate_reg = true,
};
static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
{
struct input_dev *input = priv->input;
int i;
bool contact = false, touch = false;
bool contact = false, touch;
unsigned int x = 0, y = 0;
for (i = 0; i < priv->max_touches; i++) {
if (priv->model == MODEL_ILI210X) {
touch = ili210x_touchdata_to_coords(priv, touchdata,
i, &x, &y);
} else if (priv->model == MODEL_ILI251X) {
touch = ili251x_touchdata_to_coords(priv, touchdata,
i, &x, &y);
if (touch)
contact = true;
}
for (i = 0; i < priv->chip->max_touches; i++) {
touch = priv->chip->parse_touch_data(touchdata, i, &x, &y);
input_mt_slot(input, i);
input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
if (!touch)
continue;
touchscreen_report_pos(input, &priv->prop, x, y,
true);
if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) {
touchscreen_report_pos(input, &priv->prop, x, y, true);
contact = true;
}
}
input_mt_report_pointer_emulation(input, false);
input_sync(input);
if (priv->model == MODEL_ILI210X)
contact = touchdata[0] & 0xf3;
return contact;
}
static void ili210x_work(struct work_struct *work)
{
struct ili210x *priv = container_of(work, struct ili210x,
dwork.work);
struct i2c_client *client = priv->client;
u8 touchdata[64] = { 0 };
bool touch;
int error = -EINVAL;
if (priv->model == MODEL_ILI210X) {
error = ili210x_read_reg(client, REG_TOUCHDATA,
touchdata, sizeof(touchdata));
} else if (priv->model == MODEL_ILI251X) {
error = ili210x_read_reg(client, REG_TOUCHDATA,
touchdata, 31);
if (!error && touchdata[0] == 2)
error = ili210x_read(client, &touchdata[31], 20);
}
if (error) {
dev_err(&client->dev,
"Unable to get touchdata, err = %d\n", error);
return;
}
touch = ili210x_report_events(priv, touchdata);
if (touch)
schedule_delayed_work(&priv->dwork,
msecs_to_jiffies(priv->poll_period));
}
static irqreturn_t ili210x_irq(int irq, void *irq_data)
{
struct ili210x *priv = irq_data;
struct i2c_client *client = priv->client;
const struct ili2xxx_chip *chip = priv->chip;
u8 touchdata[ILI210X_DATA_SIZE] = { 0 };
bool keep_polling;
bool touch;
int error;
schedule_delayed_work(&priv->dwork, 0);
do {
error = chip->get_touch_data(client, touchdata);
if (error) {
dev_err(&client->dev,
"Unable to get touch data: %d\n", error);
break;
}
touch = ili210x_report_events(priv, touchdata);
keep_polling = chip->continue_polling(touchdata, touch);
if (keep_polling)
msleep(ILI2XXX_POLL_PERIOD);
} while (!priv->stop && keep_polling);
return IRQ_HANDLED;
}
@ -242,8 +314,19 @@ static struct attribute *ili210x_attributes[] = {
NULL,
};
static umode_t ili210x_calibrate_visible(struct kobject *kobj,
struct attribute *attr, int index)
{
struct device *dev = kobj_to_dev(kobj);
struct i2c_client *client = to_i2c_client(dev);
struct ili210x *priv = i2c_get_clientdata(client);
return priv->chip->has_calibrate_reg;
}
static const struct attribute_group ili210x_attr_group = {
.attrs = ili210x_attributes,
.is_visible = ili210x_calibrate_visible,
};
static void ili210x_power_down(void *data)
@ -253,28 +336,35 @@ static void ili210x_power_down(void *data)
gpiod_set_value_cansleep(reset_gpio, 1);
}
static void ili210x_cancel_work(void *data)
static void ili210x_stop(void *data)
{
struct ili210x *priv = data;
cancel_delayed_work_sync(&priv->dwork);
/* Tell ISR to quit even if there is a contact. */
priv->stop = true;
}
static int ili210x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
const struct ili2xxx_chip *chip;
struct ili210x *priv;
struct gpio_desc *reset_gpio;
struct input_dev *input;
struct firmware_version firmware;
enum ili2xxx_model model;
int error;
model = (enum ili2xxx_model)id->driver_data;
unsigned int max_xy;
dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
chip = device_get_match_data(dev);
if (!chip && id)
chip = (const struct ili2xxx_chip *)id->driver_data;
if (!chip) {
dev_err(&client->dev, "unknown device model\n");
return -ENODEV;
}
if (client->irq <= 0) {
dev_err(dev, "No IRQ!\n");
return -EINVAL;
@ -305,49 +395,39 @@ static int ili210x_i2c_probe(struct i2c_client *client,
priv->client = client;
priv->input = input;
priv->poll_period = DEFAULT_POLL_PERIOD;
INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
priv->reset_gpio = reset_gpio;
priv->model = model;
if (model == MODEL_ILI210X)
priv->max_touches = ILI210X_TOUCHES;
if (model == MODEL_ILI251X)
priv->max_touches = ILI251X_TOUCHES;
priv->chip = chip;
i2c_set_clientdata(client, priv);
/* Get firmware version */
error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
&firmware, sizeof(firmware));
if (error) {
dev_err(dev, "Failed to get firmware version, err: %d\n",
error);
return error;
}
/* Setup input device */
input->name = "ILI210x Touchscreen";
input->id.bustype = BUS_I2C;
input->dev.parent = dev;
/* Multi touch */
input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
max_xy = (chip->resolution ?: SZ_64K) - 1;
input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0);
touchscreen_parse_properties(input, true, &priv->prop);
input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
error = devm_add_action(dev, ili210x_cancel_work, priv);
if (error)
error = input_mt_init_slots(input, priv->chip->max_touches,
INPUT_MT_DIRECT);
if (error) {
dev_err(dev, "Unable to set up slots, err: %d\n", error);
return error;
}
error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
client->name, priv);
error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
IRQF_ONESHOT, client->name, priv);
if (error) {
dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
error);
return error;
}
error = devm_add_action_or_reset(dev, ili210x_stop, priv);
if (error)
return error;
error = devm_device_add_group(dev, &ili210x_attr_group);
if (error) {
dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
@ -361,56 +441,28 @@ static int ili210x_i2c_probe(struct i2c_client *client,
return error;
}
device_init_wakeup(dev, 1);
dev_dbg(dev,
"ILI210x initialized (IRQ: %d), firmware version %d.%d.%d",
client->irq, firmware.id, firmware.major, firmware.minor);
return 0;
}
static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
return 0;
}
static int __maybe_unused ili210x_i2c_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
if (device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
ili210x_i2c_suspend, ili210x_i2c_resume);
static const struct i2c_device_id ili210x_i2c_id[] = {
{ "ili210x", MODEL_ILI210X },
{ "ili251x", MODEL_ILI251X },
{ "ili210x", (long)&ili210x_chip },
{ "ili2117", (long)&ili211x_chip },
{ "ili251x", (long)&ili251x_chip },
{ }
};
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
static const struct of_device_id ili210x_dt_ids[] = {
{ .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
{ .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
{ },
{ .compatible = "ilitek,ili210x", .data = &ili210x_chip },
{ .compatible = "ilitek,ili2117", .data = &ili211x_chip },
{ .compatible = "ilitek,ili251x", .data = &ili251x_chip },
{ }
};
MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
static struct i2c_driver ili210x_ts_driver = {
.driver = {
.name = "ili210x_i2c",
.pm = &ili210x_i2c_pm,
.of_match_table = ili210x_dt_ids,
},
.id_table = ili210x_i2c_id,

View File

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

View File

@ -5,22 +5,73 @@
* Copyright (C) 2010-2011 Pixcir, Inc.
*/
#include <asm/unaligned.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/platform_data/pixcir_i2c_ts.h>
#include <asm/unaligned.h>
#include <linux/module.h>
#include <linux/slab.h>
#define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
/*
* Register map
*/
#define PIXCIR_REG_POWER_MODE 51
#define PIXCIR_REG_INT_MODE 52
/*
* Power modes:
* active: max scan speed
* idle: lower scan speed with automatic transition to active on touch
* halt: datasheet says sleep but this is more like halt as the chip
* clocks are cut and it can only be brought out of this mode
* using the RESET pin.
*/
enum pixcir_power_mode {
PIXCIR_POWER_ACTIVE,
PIXCIR_POWER_IDLE,
PIXCIR_POWER_HALT,
};
#define PIXCIR_POWER_MODE_MASK 0x03
#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2)
/*
* Interrupt modes:
* periodical: interrupt is asserted periodicaly
* diff coordinates: interrupt is asserted when coordinates change
* level on touch: interrupt level asserted during touch
* pulse on touch: interrupt pulse asserted during touch
*
*/
enum pixcir_int_mode {
PIXCIR_INT_PERIODICAL,
PIXCIR_INT_DIFF_COORD,
PIXCIR_INT_LEVEL_TOUCH,
PIXCIR_INT_PULSE_TOUCH,
};
#define PIXCIR_INT_MODE_MASK 0x03
#define PIXCIR_INT_ENABLE (1UL << 3)
#define PIXCIR_INT_POL_HIGH (1UL << 2)
/**
* struct pixcir_i2c_chip_data - chip related data
* @max_fingers: Max number of fingers reported simultaneously by h/w
* @has_hw_ids: Hardware supports finger tracking IDs
*
*/
struct pixcir_i2c_chip_data {
u8 max_fingers;
bool has_hw_ids;
};
struct pixcir_i2c_ts_data {
struct i2c_client *client;
struct input_dev *input;
@ -30,7 +81,6 @@ struct pixcir_i2c_ts_data {
struct gpio_desc *gpio_wake;
const struct pixcir_i2c_chip_data *chip;
struct touchscreen_properties prop;
int max_fingers; /* Max fingers supported in this instance */
bool running;
};
@ -54,7 +104,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
memset(report, 0, sizeof(struct pixcir_report_data));
i = chip->has_hw_ids ? 1 : 0;
readsize = 2 + tsdata->max_fingers * (4 + i);
readsize = 2 + tsdata->chip->max_fingers * (4 + i);
if (readsize > sizeof(rdbuf))
readsize = sizeof(rdbuf);
@ -75,8 +125,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
}
touch = rdbuf[0] & 0x7;
if (touch > tsdata->max_fingers)
touch = tsdata->max_fingers;
if (touch > tsdata->chip->max_fingers)
touch = tsdata->chip->max_fingers;
report->num_touches = touch;
bufptr = &rdbuf[2];
@ -192,7 +242,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
dev_err(dev, "%s: can't read reg %d : %d\n",
__func__, PIXCIR_REG_POWER_MODE, ret);
return ret;
}
@ -205,7 +255,7 @@ static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
dev_err(dev, "%s: can't write reg %d : %d\n",
__func__, PIXCIR_REG_POWER_MODE, ret);
return ret;
}
@ -231,7 +281,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
dev_err(dev, "%s: can't read reg %d : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
@ -246,7 +296,7 @@ static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
dev_err(dev, "%s: can't write reg %d : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
@ -264,7 +314,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
dev_err(dev, "%s: can't read reg %d : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
@ -276,7 +326,7 @@ static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
dev_err(dev, "%s: can't write reg %d : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
@ -412,31 +462,9 @@ unlock:
static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops,
pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume);
#ifdef CONFIG_OF
static const struct of_device_id pixcir_of_match[];
static int pixcir_parse_dt(struct device *dev,
struct pixcir_i2c_ts_data *tsdata)
{
tsdata->chip = of_device_get_match_data(dev);
if (!tsdata->chip)
return -EINVAL;
return 0;
}
#else
static int pixcir_parse_dt(struct device *dev,
struct pixcir_i2c_ts_data *tsdata)
{
return -EINVAL;
}
#endif
static int pixcir_i2c_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev);
struct device *dev = &client->dev;
struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input;
@ -446,19 +474,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
if (!tsdata)
return -ENOMEM;
if (pdata) {
tsdata->chip = &pdata->chip;
} else if (dev->of_node) {
error = pixcir_parse_dt(dev, tsdata);
if (error)
return error;
} else {
dev_err(dev, "platform data not defined\n");
return -EINVAL;
}
if (!tsdata->chip->max_fingers) {
dev_err(dev, "Invalid max_fingers in chip data\n");
tsdata->chip = device_get_match_data(dev);
if (!tsdata->chip && id)
tsdata->chip = (const void *)id->driver_data;
if (!tsdata->chip) {
dev_err(dev, "can't locate chip data\n");
return -EINVAL;
}
@ -475,30 +495,17 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input->id.bustype = BUS_I2C;
input->open = pixcir_input_open;
input->close = pixcir_input_close;
input->dev.parent = dev;
if (pdata) {
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
} else {
input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
touchscreen_parse_properties(input, true, &tsdata->prop);
if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
!input_abs_get_max(input, ABS_MT_POSITION_Y)) {
dev_err(dev, "Touchscreen size is not specified\n");
return -EINVAL;
}
input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
touchscreen_parse_properties(input, true, &tsdata->prop);
if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
!input_abs_get_max(input, ABS_MT_POSITION_Y)) {
dev_err(dev, "Touchscreen size is not specified\n");
return -EINVAL;
}
tsdata->max_fingers = tsdata->chip->max_fingers;
if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
tsdata->max_fingers = PIXCIR_MAX_SLOTS;
dev_info(dev, "Limiting maximum fingers to %d\n",
tsdata->max_fingers);
}
error = input_mt_init_slots(input, tsdata->max_fingers,
error = input_mt_init_slots(input, tsdata->chip->max_fingers,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) {
dev_err(dev, "Error initializing Multi-Touch slots\n");
@ -510,7 +517,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
if (IS_ERR(tsdata->gpio_attb)) {
error = PTR_ERR(tsdata->gpio_attb);
dev_err(dev, "Failed to request ATTB gpio: %d\n", error);
if (error != -EPROBE_DEFER)
dev_err(dev, "Failed to request ATTB gpio: %d\n",
error);
return error;
}
@ -518,7 +527,9 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
GPIOD_OUT_LOW);
if (IS_ERR(tsdata->gpio_reset)) {
error = PTR_ERR(tsdata->gpio_reset);
dev_err(dev, "Failed to request RESET gpio: %d\n", error);
if (error != -EPROBE_DEFER)
dev_err(dev, "Failed to request RESET gpio: %d\n",
error);
return error;
}
@ -574,14 +585,6 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return 0;
}
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
{ "pixcir_ts", 0 },
{ "pixcir_tangoc", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
#ifdef CONFIG_OF
static const struct pixcir_i2c_chip_data pixcir_ts_data = {
.max_fingers = 2,
/* no hw id support */
@ -592,6 +595,14 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
.has_hw_ids = true,
};
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
{ "pixcir_ts", (unsigned long) &pixcir_ts_data },
{ "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
#ifdef CONFIG_OF
static const struct of_device_id pixcir_of_match[] = {
{ .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data },
{ .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data },

View File

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

View File

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

View File

@ -14,23 +14,19 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/input/touchscreen.h>
#define ST1232_TS_NAME "st1232-ts"
#define ST1633_TS_NAME "st1633-ts"
struct st1232_ts_finger {
u16 x;
u16 y;
u8 t;
bool is_valid;
};
#define ST_TS_MAX_FINGERS 10
struct st_chip_info {
bool have_z;
@ -50,81 +46,89 @@ struct st1232_ts_data {
const struct st_chip_info *chip_info;
int read_buf_len;
u8 *read_buf;
struct st1232_ts_finger *finger;
};
static int st1232_ts_read_data(struct st1232_ts_data *ts)
{
struct st1232_ts_finger *finger = ts->finger;
struct i2c_client *client = ts->client;
struct i2c_msg msg[2];
int error;
int i, y;
u8 start_reg = ts->chip_info->start_reg;
u8 *buf = ts->read_buf;
struct i2c_msg msg[] = {
{
.addr = client->addr,
.len = sizeof(start_reg),
.buf = &start_reg,
},
{
.addr = client->addr,
.flags = I2C_M_RD | I2C_M_DMA_SAFE,
.len = ts->read_buf_len,
.buf = ts->read_buf,
}
};
int ret;
/* read touchscreen data */
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &start_reg;
ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
if (ret != ARRAY_SIZE(msg))
return ret < 0 ? ret : -EIO;
msg[1].addr = ts->client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = ts->read_buf_len;
msg[1].buf = buf;
return 0;
}
error = i2c_transfer(client->adapter, msg, 2);
if (error < 0)
return error;
static int st1232_ts_parse_and_report(struct st1232_ts_data *ts)
{
struct input_dev *input = ts->input_dev;
struct input_mt_pos pos[ST_TS_MAX_FINGERS];
u8 z[ST_TS_MAX_FINGERS];
int slots[ST_TS_MAX_FINGERS];
int n_contacts = 0;
int i;
for (i = 0, y = 0; i < ts->chip_info->max_fingers; i++, y += 3) {
finger[i].is_valid = buf[i + y] >> 7;
if (finger[i].is_valid) {
finger[i].x = ((buf[i + y] & 0x0070) << 4) |
buf[i + y + 1];
finger[i].y = ((buf[i + y] & 0x0007) << 8) |
buf[i + y + 2];
for (i = 0; i < ts->chip_info->max_fingers; i++) {
u8 *buf = &ts->read_buf[i * 4];
if (buf[0] & BIT(7)) {
unsigned int x = ((buf[0] & 0x70) << 4) | buf[1];
unsigned int y = ((buf[0] & 0x07) << 8) | buf[2];
touchscreen_set_mt_pos(&pos[n_contacts],
&ts->prop, x, y);
/* st1232 includes a z-axis / touch strength */
if (ts->chip_info->have_z)
finger[i].t = buf[i + 6];
z[n_contacts] = ts->read_buf[i + 6];
n_contacts++;
}
}
return 0;
input_mt_assign_slots(input, slots, pos, n_contacts, 0);
for (i = 0; i < n_contacts; i++) {
input_mt_slot(input, slots[i]);
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
input_report_abs(input, ABS_MT_POSITION_X, pos[i].x);
input_report_abs(input, ABS_MT_POSITION_Y, pos[i].y);
if (ts->chip_info->have_z)
input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]);
}
input_mt_sync_frame(input);
input_sync(input);
return n_contacts;
}
static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
{
struct st1232_ts_data *ts = dev_id;
struct st1232_ts_finger *finger = ts->finger;
struct input_dev *input_dev = ts->input_dev;
int count = 0;
int i, ret;
int count;
int error;
ret = st1232_ts_read_data(ts);
if (ret < 0)
goto end;
error = st1232_ts_read_data(ts);
if (error)
goto out;
/* multi touch protocol */
for (i = 0; i < ts->chip_info->max_fingers; i++) {
if (!finger[i].is_valid)
continue;
if (ts->chip_info->have_z)
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
finger[i].t);
touchscreen_report_pos(input_dev, &ts->prop,
finger[i].x, finger[i].y, true);
input_mt_sync(input_dev);
count++;
}
/* SYN_MT_REPORT only if no contact */
count = st1232_ts_parse_and_report(ts);
if (!count) {
input_mt_sync(input_dev);
if (ts->low_latency_req.dev) {
dev_pm_qos_remove_request(&ts->low_latency_req);
ts->low_latency_req.dev = NULL;
@ -136,10 +140,7 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
DEV_PM_QOS_RESUME_LATENCY, 100);
}
/* SYN_REPORT */
input_sync(input_dev);
end:
out:
return IRQ_HANDLED;
}
@ -149,6 +150,11 @@ static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
}
static void st1232_ts_power_off(void *data)
{
st1232_ts_power(data, false);
}
static const struct st_chip_info st1232_chip_info = {
.have_z = true,
.max_x = 0x31f, /* 800 - 1 */
@ -172,7 +178,6 @@ static int st1232_ts_probe(struct i2c_client *client,
{
const struct st_chip_info *match;
struct st1232_ts_data *ts;
struct st1232_ts_finger *finger;
struct input_dev *input_dev;
int error;
@ -199,11 +204,6 @@ static int st1232_ts_probe(struct i2c_client *client,
return -ENOMEM;
ts->chip_info = match;
ts->finger = devm_kcalloc(&client->dev,
ts->chip_info->max_fingers, sizeof(*finger),
GFP_KERNEL);
if (!ts->finger)
return -ENOMEM;
/* allocate a buffer according to the number of registers to read */
ts->read_buf_len = ts->chip_info->max_fingers * 4;
@ -229,14 +229,15 @@ static int st1232_ts_probe(struct i2c_client *client,
st1232_ts_power(ts, true);
error = devm_add_action_or_reset(&client->dev, st1232_ts_power_off, ts);
if (error) {
dev_err(&client->dev,
"Failed to install power off action: %d\n", error);
return error;
}
input_dev->name = "st1232-touchscreen";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
__set_bit(EV_SYN, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_ABS, input_dev->evbit);
if (ts->chip_info->have_z)
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0,
@ -249,6 +250,14 @@ static int st1232_ts_probe(struct i2c_client *client,
touchscreen_parse_properties(input_dev, true, &ts->prop);
error = input_mt_init_slots(input_dev, ts->chip_info->max_fingers,
INPUT_MT_DIRECT | INPUT_MT_TRACK |
INPUT_MT_DROP_UNUSED);
if (error) {
dev_err(&client->dev, "failed to initialize MT slots\n");
return error;
}
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, st1232_ts_irq_handler,
IRQF_ONESHOT,
@ -266,16 +275,6 @@ static int st1232_ts_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, ts);
device_init_wakeup(&client->dev, 1);
return 0;
}
static int st1232_ts_remove(struct i2c_client *client)
{
struct st1232_ts_data *ts = i2c_get_clientdata(client);
st1232_ts_power(ts, false);
return 0;
}
@ -285,12 +284,10 @@ static int __maybe_unused st1232_ts_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev)) {
enable_irq_wake(client->irq);
} else {
disable_irq(client->irq);
disable_irq(client->irq);
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, false);
}
return 0;
}
@ -300,12 +297,10 @@ static int __maybe_unused st1232_ts_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct st1232_ts_data *ts = i2c_get_clientdata(client);
if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq);
} else {
if (!device_may_wakeup(&client->dev))
st1232_ts_power(ts, true);
enable_irq(client->irq);
}
enable_irq(client->irq);
return 0;
}
@ -329,7 +324,6 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids);
static struct i2c_driver st1232_ts_driver = {
.probe = st1232_ts_probe,
.remove = st1232_ts_remove,
.id_table = st1232_ts_id,
.driver = {
.name = ST1232_TS_NAME,

View File

@ -27,7 +27,7 @@
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/printk.h>
#include <linux/input-polldev.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/usb/input.h>
#include <linux/videodev2.h>
@ -206,7 +206,7 @@ struct sur40_state {
struct usb_device *usbdev;
struct device *dev;
struct input_polled_dev *input;
struct input_dev *input;
struct v4l2_device v4l2;
struct video_device vdev;
@ -370,6 +370,10 @@ static int sur40_init(struct sur40_state *dev)
goto error;
result = sur40_command(dev, SUR40_GET_VERSION, 0x03, buffer, 12);
if (result < 0)
goto error;
result = 0;
/*
* Discard the result buffer - no known data inside except
@ -381,22 +385,22 @@ error:
}
/*
* Callback routines from input_polled_dev
* Callback routines from input_dev
*/
/* Enable the device, polling will now start. */
static void sur40_open(struct input_polled_dev *polldev)
static int sur40_open(struct input_dev *input)
{
struct sur40_state *sur40 = polldev->private;
struct sur40_state *sur40 = input_get_drvdata(input);
dev_dbg(sur40->dev, "open\n");
sur40_init(sur40);
return sur40_init(sur40);
}
/* Disable device, polling has stopped. */
static void sur40_close(struct input_polled_dev *polldev)
static void sur40_close(struct input_dev *input)
{
struct sur40_state *sur40 = polldev->private;
struct sur40_state *sur40 = input_get_drvdata(input);
dev_dbg(sur40->dev, "close\n");
/*
@ -448,10 +452,9 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
}
/* core function: poll for new input data */
static void sur40_poll(struct input_polled_dev *polldev)
static void sur40_poll(struct input_dev *input)
{
struct sur40_state *sur40 = polldev->private;
struct input_dev *input = polldev->input;
struct sur40_state *sur40 = input_get_drvdata(input);
int result, bulk_read, need_blobs, packet_blobs, i;
u32 uninitialized_var(packet_id);
@ -613,10 +616,9 @@ err_poll:
}
/* Initialize input device parameters. */
static void sur40_input_setup(struct input_dev *input_dev)
static int sur40_input_setup_events(struct input_dev *input_dev)
{
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_ABS, input_dev->evbit);
int error;
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
0, SENSOR_RES_X, 0, 0);
@ -637,8 +639,14 @@ static void sur40_input_setup(struct input_dev *input_dev)
input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
input_mt_init_slots(input_dev, MAX_CONTACTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
error = input_mt_init_slots(input_dev, MAX_CONTACTS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) {
dev_err(input_dev->dev.parent, "failed to set up slots\n");
return error;
}
return 0;
}
/* Check candidate USB interface. */
@ -649,7 +657,7 @@ static int sur40_probe(struct usb_interface *interface,
struct sur40_state *sur40;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
struct input_polled_dev *poll_dev;
struct input_dev *input;
int error;
/* Check if we really have the right interface. */
@ -670,8 +678,8 @@ static int sur40_probe(struct usb_interface *interface,
if (!sur40)
return -ENOMEM;
poll_dev = input_allocate_polled_device();
if (!poll_dev) {
input = input_allocate_device();
if (!input) {
error = -ENOMEM;
goto err_free_dev;
}
@ -681,26 +689,33 @@ static int sur40_probe(struct usb_interface *interface,
spin_lock_init(&sur40->qlock);
mutex_init(&sur40->lock);
/* Set up polled input device control structure */
poll_dev->private = sur40;
poll_dev->poll_interval = POLL_INTERVAL;
poll_dev->open = sur40_open;
poll_dev->poll = sur40_poll;
poll_dev->close = sur40_close;
/* Set up regular input device structure */
sur40_input_setup(poll_dev->input);
poll_dev->input->name = DRIVER_LONG;
usb_to_input_id(usbdev, &poll_dev->input->id);
input->name = DRIVER_LONG;
usb_to_input_id(usbdev, &input->id);
usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
poll_dev->input->phys = sur40->phys;
poll_dev->input->dev.parent = &interface->dev;
input->phys = sur40->phys;
input->dev.parent = &interface->dev;
input->open = sur40_open;
input->close = sur40_close;
error = sur40_input_setup_events(input);
if (error)
goto err_free_input;
input_set_drvdata(input, sur40);
error = input_setup_polling(input, sur40_poll);
if (error) {
dev_err(&interface->dev, "failed to set up polling");
goto err_free_input;
}
input_set_poll_interval(input, POLL_INTERVAL);
sur40->usbdev = usbdev;
sur40->dev = &interface->dev;
sur40->input = poll_dev;
sur40->input = input;
/* use the bulk-in endpoint tested above */
sur40->bulk_in_size = usb_endpoint_maxp(endpoint);
@ -709,11 +724,11 @@ static int sur40_probe(struct usb_interface *interface,
if (!sur40->bulk_in_buffer) {
dev_err(&interface->dev, "Unable to allocate input buffer.");
error = -ENOMEM;
goto err_free_polldev;
goto err_free_input;
}
/* register the polled input device */
error = input_register_polled_device(poll_dev);
error = input_register_device(input);
if (error) {
dev_err(&interface->dev,
"Unable to register polled input device.");
@ -796,8 +811,8 @@ err_unreg_v4l2:
v4l2_device_unregister(&sur40->v4l2);
err_free_buffer:
kfree(sur40->bulk_in_buffer);
err_free_polldev:
input_free_polled_device(sur40->input);
err_free_input:
input_free_device(input);
err_free_dev:
kfree(sur40);
@ -813,8 +828,7 @@ static void sur40_disconnect(struct usb_interface *interface)
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
input_unregister_polled_device(sur40->input);
input_free_polled_device(sur40->input);
input_unregister_device(sur40->input);
kfree(sur40->bulk_in_buffer);
kfree(sur40);

View File

@ -17,7 +17,6 @@
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/platform_device.h>
#include <linux/mfd/tps6507x.h>
#include <linux/input/tps6507x-ts.h>
@ -40,7 +39,7 @@ struct ts_event {
struct tps6507x_ts {
struct device *dev;
struct input_polled_dev *poll_dev;
struct input_dev *input;
struct tps6507x_dev *mfd;
char phys[32];
struct ts_event tc;
@ -148,10 +147,9 @@ static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
return ret;
}
static void tps6507x_ts_poll(struct input_polled_dev *poll_dev)
static void tps6507x_ts_poll(struct input_dev *input_dev)
{
struct tps6507x_ts *tsc = poll_dev->private;
struct input_dev *input_dev = poll_dev->input;
struct tps6507x_ts *tsc = input_get_drvdata(input_dev);
bool pendown;
s32 ret;
@ -205,7 +203,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
const struct tps6507x_board *tps_board;
const struct touchscreen_init_data *init_data;
struct tps6507x_ts *tsc;
struct input_polled_dev *poll_dev;
struct input_dev *input_dev;
int error;
@ -240,23 +237,16 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
snprintf(tsc->phys, sizeof(tsc->phys),
"%s/input0", dev_name(tsc->dev));
poll_dev = devm_input_allocate_polled_device(&pdev->dev);
if (!poll_dev) {
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev) {
dev_err(tsc->dev, "Failed to allocate polled input device.\n");
return -ENOMEM;
}
tsc->poll_dev = poll_dev;
poll_dev->private = tsc;
poll_dev->poll = tps6507x_ts_poll;
poll_dev->poll_interval = init_data ?
init_data->poll_period : TSC_DEFAULT_POLL_PERIOD;
input_dev = poll_dev->input;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
tsc->input = input_dev;
input_set_drvdata(input_dev, tsc);
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
@ -275,7 +265,15 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
if (error)
return error;
error = input_register_polled_device(poll_dev);
error = input_setup_polling(input_dev, tps6507x_ts_poll);
if (error)
return error;
input_set_poll_interval(input_dev,
init_data ? init_data->poll_period :
TSC_DEFAULT_POLL_PERIOD);
error = input_register_device(input_dev);
if (error)
return error;

View File

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

View File

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

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

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