Commit f78e9de8 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull input updates from Dmitry Torokhov:
 "Just one new driver (Cypress StreetFighter touchkey), and no input
  core changes this time.

  Plus various fixes and enhancements to existing drivers"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (54 commits)
  Input: iforce - fix control-message timeout
  Input: wacom_i2c - use macros for the bit masks
  Input: ili210x - reduce sample period to 15ms
  Input: ili210x - improve polled sample spacing
  Input: ili210x - special case ili251x sample read out
  Input: elantench - fix misreporting trackpoint coordinates
  Input: synaptics-rmi4 - Fix device hierarchy
  Input: i8042 - Add quirk for Fujitsu Lifebook T725
  Input: cap11xx - add support for cap1206
  Input: remove unused header <linux/input/cy8ctmg110_pdata.h>
  Input: ili210x - add ili251x firmware update support
  Input: ili210x - export ili251x version details via sysfs
  Input: ili210x - use resolution from ili251x firmware
  Input: pm8941-pwrkey - respect reboot_mode for warm reset
  reboot: export symbol 'reboot_mode'
  Input: max77693-haptic - drop unneeded MODULE_ALIAS
  Input: cpcap-pwrbutton - do not set input parent explicitly
  Input: max8925_onkey - don't mark comment as kernel-doc
  Input: ads7846 - do not attempt IRQ workaround when deferring probe
  Input: ads7846 - use input_set_capability()
  ...
parents 3b81bf78 efe6f16c
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/cypress-sf.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cypress StreetFighter touchkey controller
maintainers:
- Yassine Oudjana <y.oudjana@protonmail.com>
allOf:
- $ref: input.yaml#
properties:
compatible:
const: cypress,sf3155
reg:
maxItems: 1
interrupts:
maxItems: 1
avdd-supply:
description: Regulator for AVDD analog voltage
vdd-supply:
description: Regulator for VDD digital voltage
linux,keycodes:
minItems: 1
maxItems: 8
required:
- compatible
- reg
- interrupts
- avdd-supply
- vdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
touchkey@28 {
compatible = "cypress,sf3155";
reg = <0x28>;
interrupt-parent = <&msmgpio>;
interrupts = <77 IRQ_TYPE_EDGE_FALLING>;
avdd-supply = <&vreg_l6a_1p8>;
vdd-supply = <&vdd_3v2_tp>;
linux,keycodes = <KEY_BACK KEY_MENU>;
};
};
...@@ -19,6 +19,7 @@ properties: ...@@ -19,6 +19,7 @@ properties:
- microchip,cap1106 - microchip,cap1106
- microchip,cap1126 - microchip,cap1126
- microchip,cap1188 - microchip,cap1188
- microchip,cap1206
reg: reg:
maxItems: 1 maxItems: 1
......
...@@ -4459,7 +4459,7 @@ CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER ...@@ -4459,7 +4459,7 @@ CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com> M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org L: linux-input@vger.kernel.org
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/chipone_icn8318.txt F: Documentation/devicetree/bindings/input/touchscreen/chipone,icn8318.yaml
F: drivers/input/touchscreen/chipone_icn8318.c F: drivers/input/touchscreen/chipone_icn8318.c
CHIPONE ICN8505 I2C TOUCHSCREEN DRIVER CHIPONE ICN8505 I2C TOUCHSCREEN DRIVER
...@@ -5205,6 +5205,13 @@ L: linux-input@vger.kernel.org ...@@ -5205,6 +5205,13 @@ L: linux-input@vger.kernel.org
S: Maintained S: Maintained
F: drivers/input/touchscreen/cy8ctma140.c F: drivers/input/touchscreen/cy8ctma140.c
CYPRESS STREETFIGHTER TOUCHKEYS DRIVER
M: Yassine Oudjana <y.oudjana@protonmail.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/cypress-sf.yaml
F: drivers/input/keyboard/cypress-sf.c
CYTTSP TOUCHSCREEN DRIVER CYTTSP TOUCHSCREEN DRIVER
M: Linus Walleij <linus.walleij@linaro.org> M: Linus Walleij <linus.walleij@linaro.org>
L: linux-input@vger.kernel.org L: linux-input@vger.kernel.org
...@@ -8063,9 +8070,10 @@ F: drivers/media/usb/go7007/ ...@@ -8063,9 +8070,10 @@ F: drivers/media/usb/go7007/
GOODIX TOUCHSCREEN GOODIX TOUCHSCREEN
M: Bastien Nocera <hadess@hadess.net> M: Bastien Nocera <hadess@hadess.net>
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org L: linux-input@vger.kernel.org
S: Maintained S: Maintained
F: drivers/input/touchscreen/goodix.c F: drivers/input/touchscreen/goodix*
GOOGLE ETHERNET DRIVERS GOOGLE ETHERNET DRIVERS
M: Jeroen de Borst <jeroendb@google.com> M: Jeroen de Borst <jeroendb@google.com>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/gameport.h> #include <linux/gameport.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/seq_buf.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/timekeeping.h> #include <linux/timekeeping.h>
...@@ -338,23 +339,24 @@ static void analog_calibrate_timer(struct analog_port *port) ...@@ -338,23 +339,24 @@ static void analog_calibrate_timer(struct analog_port *port)
static void analog_name(struct analog *analog) static void analog_name(struct analog *analog)
{ {
snprintf(analog->name, sizeof(analog->name), "Analog %d-axis %d-button", struct seq_buf s;
seq_buf_init(&s, analog->name, sizeof(analog->name));
seq_buf_printf(&s, "Analog %d-axis %d-button",
hweight8(analog->mask & ANALOG_AXES_STD), hweight8(analog->mask & ANALOG_AXES_STD),
hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 + hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4); hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
if (analog->mask & ANALOG_HATS_ALL) if (analog->mask & ANALOG_HATS_ALL)
snprintf(analog->name, sizeof(analog->name), "%s %d-hat", seq_buf_printf(&s, " %d-hat",
analog->name, hweight16(analog->mask & ANALOG_HATS_ALL)); hweight16(analog->mask & ANALOG_HATS_ALL));
if (analog->mask & ANALOG_HAT_FCS) if (analog->mask & ANALOG_HAT_FCS)
strlcat(analog->name, " FCS", sizeof(analog->name)); seq_buf_printf(&s, " FCS");
if (analog->mask & ANALOG_ANY_CHF) if (analog->mask & ANALOG_ANY_CHF)
strlcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF", seq_buf_printf(&s, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
sizeof(analog->name));
strlcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick", seq_buf_printf(&s, (analog->mask & ANALOG_GAMEPAD) ? " gamepad" : " joystick");
sizeof(analog->name));
} }
/* /*
......
...@@ -92,7 +92,7 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 id, ...@@ -92,7 +92,7 @@ static int iforce_usb_get_id(struct iforce *iforce, u8 id,
id, id,
USB_TYPE_VENDOR | USB_DIR_IN | USB_TYPE_VENDOR | USB_DIR_IN |
USB_RECIP_INTERFACE, USB_RECIP_INTERFACE,
0, 0, buf, IFORCE_MAX_LENGTH, HZ); 0, 0, buf, IFORCE_MAX_LENGTH, 1000);
if (status < 0) { if (status < 0) {
dev_err(&iforce_usb->intf->dev, dev_err(&iforce_usb->intf->dev,
"usb_submit_urb failed: %d\n", status); "usb_submit_urb failed: %d\n", status);
......
...@@ -83,7 +83,7 @@ static const struct tmdc_model { ...@@ -83,7 +83,7 @@ static const struct tmdc_model {
const signed char *axes; const signed char *axes;
const short *buttons; const short *buttons;
} tmdc_models[] = { } tmdc_models[] = {
{ 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy }, { 1, "ThrustMaster Millennium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
{ 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad }, { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
{ 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at }, { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
{ 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm }, { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
......
...@@ -788,4 +788,14 @@ config KEYBOARD_MTK_PMIC ...@@ -788,4 +788,14 @@ config KEYBOARD_MTK_PMIC
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called pmic-keys. module will be called pmic-keys.
config KEYBOARD_CYPRESS_SF
tristate "Cypress StreetFighter touchkey support"
depends on I2C
help
Say Y here if you want to enable support for Cypress StreetFighter
touchkeys.
To compile this driver as a module, choose M here: the
module will be called cypress-sf.
endif endif
...@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o ...@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o
obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_CYPRESS_SF) += cypress-sf.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
......
...@@ -91,18 +91,21 @@ struct cap11xx_hw_model { ...@@ -91,18 +91,21 @@ struct cap11xx_hw_model {
u8 product_id; u8 product_id;
unsigned int num_channels; unsigned int num_channels;
unsigned int num_leds; unsigned int num_leds;
bool no_gain;
}; };
enum { enum {
CAP1106, CAP1106,
CAP1126, CAP1126,
CAP1188, CAP1188,
CAP1206,
}; };
static const struct cap11xx_hw_model cap11xx_devices[] = { static const struct cap11xx_hw_model cap11xx_devices[] = {
[CAP1106] = { .product_id = 0x55, .num_channels = 6, .num_leds = 0 }, [CAP1106] = { .product_id = 0x55, .num_channels = 6, .num_leds = 0, .no_gain = false },
[CAP1126] = { .product_id = 0x53, .num_channels = 6, .num_leds = 2 }, [CAP1126] = { .product_id = 0x53, .num_channels = 6, .num_leds = 2, .no_gain = false },
[CAP1188] = { .product_id = 0x50, .num_channels = 8, .num_leds = 8 }, [CAP1188] = { .product_id = 0x50, .num_channels = 8, .num_leds = 8, .no_gain = false },
[CAP1206] = { .product_id = 0x67, .num_channels = 6, .num_leds = 0, .no_gain = true },
}; };
static const struct reg_default cap11xx_reg_defaults[] = { static const struct reg_default cap11xx_reg_defaults[] = {
...@@ -378,17 +381,24 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client, ...@@ -378,17 +381,24 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
node = dev->of_node; node = dev->of_node;
if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) { if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
if (is_power_of_2(gain32) && gain32 <= 8) if (cap->no_gain)
dev_warn(dev,
"This version doesn't support sensor gain\n");
else if (is_power_of_2(gain32) && gain32 <= 8)
gain = ilog2(gain32); gain = ilog2(gain32);
else else
dev_err(dev, "Invalid sensor-gain value %d\n", gain32); dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
} }
if (of_property_read_bool(node, "microchip,irq-active-high")) { if (id->driver_data != CAP1206) {
error = regmap_update_bits(priv->regmap, CAP11XX_REG_CONFIG2, if (of_property_read_bool(node, "microchip,irq-active-high")) {
CAP11XX_REG_CONFIG2_ALT_POL, 0); error = regmap_update_bits(priv->regmap,
if (error) CAP11XX_REG_CONFIG2,
return error; CAP11XX_REG_CONFIG2_ALT_POL,
0);
if (error)
return error;
}
} }
/* Provide some useful defaults */ /* Provide some useful defaults */
...@@ -398,11 +408,14 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client, ...@@ -398,11 +408,14 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
of_property_read_u32_array(node, "linux,keycodes", of_property_read_u32_array(node, "linux,keycodes",
priv->keycodes, cap->num_channels); priv->keycodes, cap->num_channels);
error = regmap_update_bits(priv->regmap, CAP11XX_REG_MAIN_CONTROL, if (!cap->no_gain) {
CAP11XX_REG_MAIN_CONTROL_GAIN_MASK, error = regmap_update_bits(priv->regmap,
gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT); CAP11XX_REG_MAIN_CONTROL,
if (error) CAP11XX_REG_MAIN_CONTROL_GAIN_MASK,
return error; gain << CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT);
if (error)
return error;
}
/* Disable autorepeat. The Linux input system has its own handling. */ /* Disable autorepeat. The Linux input system has its own handling. */
error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0); error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
...@@ -470,6 +483,7 @@ static const struct of_device_id cap11xx_dt_ids[] = { ...@@ -470,6 +483,7 @@ static const struct of_device_id cap11xx_dt_ids[] = {
{ .compatible = "microchip,cap1106", }, { .compatible = "microchip,cap1106", },
{ .compatible = "microchip,cap1126", }, { .compatible = "microchip,cap1126", },
{ .compatible = "microchip,cap1188", }, { .compatible = "microchip,cap1188", },
{ .compatible = "microchip,cap1206", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, cap11xx_dt_ids); MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
...@@ -478,6 +492,7 @@ static const struct i2c_device_id cap11xx_i2c_ids[] = { ...@@ -478,6 +492,7 @@ static const struct i2c_device_id cap11xx_i2c_ids[] = {
{ "cap1106", CAP1106 }, { "cap1106", CAP1106 },
{ "cap1126", CAP1126 }, { "cap1126", CAP1126 },
{ "cap1188", CAP1188 }, { "cap1188", CAP1188 },
{ "cap1206", CAP1206 },
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids); MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids);
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Cypress StreetFighter Touchkey Driver
*
* Copyright (c) 2021 Yassine Oudjana <y.oudjana@protonmail.com>
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/regulator/consumer.h>
#define CYPRESS_SF_DEV_NAME "cypress-sf"
#define CYPRESS_SF_REG_BUTTON_STATUS 0x4a
struct cypress_sf_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct regulator_bulk_data regulators[2];
u32 *keycodes;
unsigned long keystates;
int num_keys;
};
static irqreturn_t cypress_sf_irq_handler(int irq, void *devid)
{
struct cypress_sf_data *touchkey = devid;
unsigned long keystates, changed;
bool new_state;
int val, key;
val = i2c_smbus_read_byte_data(touchkey->client,
CYPRESS_SF_REG_BUTTON_STATUS);
if (val < 0) {
dev_err(&touchkey->client->dev,
"Failed to read button status: %d", val);
return IRQ_NONE;
}
keystates = val;
bitmap_xor(&changed, &keystates, &touchkey->keystates,
touchkey->num_keys);
for_each_set_bit(key, &changed, touchkey->num_keys) {
new_state = keystates & BIT(key);
dev_dbg(&touchkey->client->dev,
"Key %d changed to %d", key, new_state);
input_report_key(touchkey->input_dev,
touchkey->keycodes[key], new_state);
}
input_sync(touchkey->input_dev);
touchkey->keystates = keystates;
return IRQ_HANDLED;
}
static int cypress_sf_probe(struct i2c_client *client)
{
struct cypress_sf_data *touchkey;
int key, error;
touchkey = devm_kzalloc(&client->dev, sizeof(*touchkey), GFP_KERNEL);
if (!touchkey)
return -ENOMEM;
touchkey->client = client;
i2c_set_clientdata(client, touchkey);
touchkey->regulators[0].supply = "vdd";
touchkey->regulators[1].supply = "avdd";
error = devm_regulator_bulk_get(&client->dev,
ARRAY_SIZE(touchkey->regulators),
touchkey->regulators);
if (error) {
dev_err(&client->dev, "Failed to get regulators: %d\n", error);
return error;
}
touchkey->num_keys = device_property_read_u32_array(&client->dev,
"linux,keycodes",
NULL, 0);
if (touchkey->num_keys < 0) {
/* Default key count */
touchkey->num_keys = 2;
}
touchkey->keycodes = devm_kcalloc(&client->dev,
touchkey->num_keys,
sizeof(*touchkey->keycodes),
GFP_KERNEL);
if (!touchkey->keycodes)
return -ENOMEM;
error = device_property_read_u32_array(&client->dev, "linux,keycodes",
touchkey->keycodes,
touchkey->num_keys);
if (error) {
dev_warn(&client->dev,
"Failed to read keycodes: %d, using defaults\n",
error);
/* Default keycodes */
touchkey->keycodes[0] = KEY_BACK;
touchkey->keycodes[1] = KEY_MENU;
}
error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators),
touchkey->regulators);
if (error) {
dev_err(&client->dev,
"Failed to enable regulators: %d\n", error);
return error;
}
touchkey->input_dev = devm_input_allocate_device(&client->dev);
if (!touchkey->input_dev) {
dev_err(&client->dev, "Failed to allocate input device\n");
return -ENOMEM;
}
touchkey->input_dev->name = CYPRESS_SF_DEV_NAME;
touchkey->input_dev->id.bustype = BUS_I2C;
for (key = 0; key < touchkey->num_keys; ++key)
input_set_capability(touchkey->input_dev,
EV_KEY, touchkey->keycodes[key]);
error = input_register_device(touchkey->input_dev);
if (error) {
dev_err(&client->dev,
"Failed to register input device: %d\n", error);
return error;
}
error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, cypress_sf_irq_handler,
IRQF_ONESHOT,
CYPRESS_SF_DEV_NAME, touchkey);
if (error) {
dev_err(&client->dev,
"Failed to register threaded irq: %d", error);
return error;
}
return 0;
};
static int __maybe_unused cypress_sf_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cypress_sf_data *touchkey = i2c_get_clientdata(client);
int error;
disable_irq(client->irq);
error = regulator_bulk_disable(ARRAY_SIZE(touchkey->regulators),
touchkey->regulators);
if (error) {
dev_err(dev, "Failed to disable regulators: %d", error);
enable_irq(client->irq);
return error;
}
return 0;
}
static int __maybe_unused cypress_sf_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cypress_sf_data *touchkey = i2c_get_clientdata(client);
int error;
error = regulator_bulk_enable(ARRAY_SIZE(touchkey->regulators),
touchkey->regulators);
if (error) {
dev_err(dev, "Failed to enable regulators: %d", error);
return error;
}
enable_irq(client->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
cypress_sf_suspend, cypress_sf_resume);
static struct i2c_device_id cypress_sf_id_table[] = {
{ CYPRESS_SF_DEV_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cypress_sf_id_table);
#ifdef CONFIG_OF
static const struct of_device_id cypress_sf_of_match[] = {
{ .compatible = "cypress,sf3155", },
{ },
};
MODULE_DEVICE_TABLE(of, cypress_sf_of_match);
#endif
static struct i2c_driver cypress_sf_driver = {
.driver = {
.name = CYPRESS_SF_DEV_NAME,
.pm = &cypress_sf_pm_ops,
.of_match_table = of_match_ptr(cypress_sf_of_match),
},
.id_table = cypress_sf_id_table,
.probe_new = cypress_sf_probe,
};
module_i2c_driver(cypress_sf_driver);
MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
MODULE_DESCRIPTION("Cypress StreetFighter Touchkey Driver");
MODULE_LICENSE("GPL v2");
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
* flag. * flag.
*/ */
#include <linux/bits.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/soc/cirrus/ep93xx.h> #include <linux/soc/cirrus/ep93xx.h>
#include <linux/platform_data/keypad-ep93xx.h> #include <linux/platform_data/keypad-ep93xx.h>
#include <linux/pm_wakeirq.h>
/* /*
* Keypad Interface Register offsets * Keypad Interface Register offsets
...@@ -35,28 +37,28 @@ ...@@ -35,28 +37,28 @@
#define KEY_REG 0x08 /* Key Value Capture register */ #define KEY_REG 0x08 /* Key Value Capture register */
/* Key Scan Initialization Register bit defines */ /* Key Scan Initialization Register bit defines */
#define KEY_INIT_DBNC_MASK (0x00ff0000) #define KEY_INIT_DBNC_MASK GENMASK(23, 16)
#define KEY_INIT_DBNC_SHIFT (16) #define KEY_INIT_DBNC_SHIFT 16
#define KEY_INIT_DIS3KY (1<<15) #define KEY_INIT_DIS3KY BIT(15)
#define KEY_INIT_DIAG (1<<14) #define KEY_INIT_DIAG BIT(14)
#define KEY_INIT_BACK (1<<13) #define KEY_INIT_BACK BIT(13)
#define KEY_INIT_T2 (1<<12) #define KEY_INIT_T2 BIT(12)
#define KEY_INIT_PRSCL_MASK (0x000003ff) #define KEY_INIT_PRSCL_MASK GENMASK(9, 0)
#define KEY_INIT_PRSCL_SHIFT (0) #define KEY_INIT_PRSCL_SHIFT 0
/* Key Scan Diagnostic Register bit defines */ /* Key Scan Diagnostic Register bit defines */
#define KEY_DIAG_MASK (0x0000003f) #define KEY_DIAG_MASK GENMASK(5, 0)
#define KEY_DIAG_SHIFT (0) #define KEY_DIAG_SHIFT 0
/* Key Value Capture Register bit defines */ /* Key Value Capture Register bit defines */
#define KEY_REG_K (1<<15) #define KEY_REG_K BIT(15)
#define KEY_REG_INT (1<<14) #define KEY_REG_INT BIT(14)
#define KEY_REG_2KEYS (1<<13) #define KEY_REG_2KEYS BIT(13)
#define KEY_REG_1KEY (1<<12) #define KEY_REG_1KEY BIT(12)
#define KEY_REG_KEY2_MASK (0x00000fc0) #define KEY_REG_KEY2_MASK GENMASK(11, 6)
#define KEY_REG_KEY2_SHIFT (6) #define KEY_REG_KEY2_SHIFT 6
#define KEY_REG_KEY1_MASK (0x0000003f) #define KEY_REG_KEY1_MASK GENMASK(5, 0)
#define KEY_REG_KEY1_SHIFT (0) #define KEY_REG_KEY1_SHIFT 0
#define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS) #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
...@@ -175,8 +177,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) ...@@ -175,8 +177,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev)
} }
#ifdef CONFIG_PM_SLEEP static int __maybe_unused ep93xx_keypad_suspend(struct device *dev)
static int ep93xx_keypad_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
...@@ -191,21 +192,15 @@ static int ep93xx_keypad_suspend(struct device *dev) ...@@ -191,21 +192,15 @@ static int ep93xx_keypad_suspend(struct device *dev)
mutex_unlock(&input_dev->mutex); mutex_unlock(&input_dev->mutex);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(keypad->irq);
return 0; return 0;
} }
static int ep93xx_keypad_resume(struct device *dev) static int __maybe_unused ep93xx_keypad_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
struct input_dev *input_dev = keypad->input_dev; struct input_dev *input_dev = keypad->input_dev;
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(keypad->irq);
mutex_lock(&input_dev->mutex); mutex_lock(&input_dev->mutex);
if (input_device_enabled(input_dev)) { if (input_device_enabled(input_dev)) {
...@@ -220,11 +215,17 @@ static int ep93xx_keypad_resume(struct device *dev) ...@@ -220,11 +215,17 @@ static int ep93xx_keypad_resume(struct device *dev)
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
ep93xx_keypad_suspend, ep93xx_keypad_resume); ep93xx_keypad_suspend, ep93xx_keypad_resume);
static void ep93xx_keypad_release_gpio_action(void *_pdev)
{
struct platform_device *pdev = _pdev;
ep93xx_keypad_release_gpio(pdev);
}
static int ep93xx_keypad_probe(struct platform_device *pdev) static int ep93xx_keypad_probe(struct platform_device *pdev)
{ {
struct ep93xx_keypad *keypad; struct ep93xx_keypad *keypad;
...@@ -233,61 +234,46 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) ...@@ -233,61 +234,46 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
int err; int err;
keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
if (!keypad) if (!keypad)
return -ENOMEM; return -ENOMEM;
keypad->pdata = dev_get_platdata(&pdev->dev); keypad->pdata = dev_get_platdata(&pdev->dev);
if (!keypad->pdata) { if (!keypad->pdata)
err = -EINVAL; return -EINVAL;
goto failed_free;
}
keymap_data = keypad->pdata->keymap_data; keymap_data = keypad->pdata->keymap_data;
if (!keymap_data) { if (!keymap_data)
err = -EINVAL; return -EINVAL;
goto failed_free;
}
keypad->irq = platform_get_irq(pdev, 0); keypad->irq = platform_get_irq(pdev, 0);
if (keypad->irq < 0) { if (keypad->irq < 0)
err = keypad->irq; return keypad->irq;
goto failed_free;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res)
err = -ENXIO; return -ENXIO;
goto failed_free;
}
res = request_mem_region(res->start, resource_size(res), pdev->name); keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
if (!res) { if (IS_ERR(keypad->mmio_base))
err = -EBUSY; return PTR_ERR(keypad->mmio_base);
goto failed_free;
}
keypad->mmio_base = ioremap(res->start, resource_size(res));
if (keypad->mmio_base == NULL) {
err = -ENXIO;
goto failed_free_mem;
}
err = ep93xx_keypad_acquire_gpio(pdev); err = ep93xx_keypad_acquire_gpio(pdev);
if (err) if (err)
goto failed_free_io; return err;
keypad->clk = clk_get(&pdev->dev, NULL); err = devm_add_action_or_reset(&pdev->dev,
if (IS_ERR(keypad->clk)) { ep93xx_keypad_release_gpio_action, pdev);
err = PTR_ERR(keypad->clk); if (err)
goto failed_free_gpio; return err;
}
input_dev = input_allocate_device(); keypad->clk = devm_clk_get(&pdev->dev, NULL);
if (!input_dev) { if (IS_ERR(keypad->clk))
err = -ENOMEM; return PTR_ERR(keypad->clk);
goto failed_put_clk;
} input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev)
return -ENOMEM;
keypad->input_dev = input_dev; keypad->input_dev = input_dev;
...@@ -295,70 +281,40 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) ...@@ -295,70 +281,40 @@ static int ep93xx_keypad_probe(struct platform_device *pdev)
input_dev->id.bustype = BUS_HOST; input_dev->id.bustype = BUS_HOST;
input_dev->open = ep93xx_keypad_open; input_dev->open = ep93xx_keypad_open;
input_dev->close = ep93xx_keypad_close; input_dev->close = ep93xx_keypad_close;
input_dev->dev.parent = &pdev->dev;
err = matrix_keypad_build_keymap(keymap_data, NULL, err = matrix_keypad_build_keymap(keymap_data, NULL,
EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS, EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
keypad->keycodes, input_dev); keypad->keycodes, input_dev);
if (err) if (err)
goto failed_free_dev; return err;
if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
__set_bit(EV_REP, input_dev->evbit); __set_bit(EV_REP, input_dev->evbit);
input_set_drvdata(input_dev, keypad); input_set_drvdata(input_dev, keypad);
err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, err = devm_request_irq(&pdev->dev, keypad->irq,
0, pdev->name, keypad); ep93xx_keypad_irq_handler,
0, pdev->name, keypad);
if (err) if (err)
goto failed_free_dev; return err;
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) if (err)
goto failed_free_irq; return err;
platform_set_drvdata(pdev, keypad); platform_set_drvdata(pdev, keypad);
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
err = dev_pm_set_wake_irq(&pdev->dev, keypad->irq);
if (err)
dev_warn(&pdev->dev, "failed to set up wakeup irq: %d\n", err);
return 0; return 0;
failed_free_irq:
free_irq(keypad->irq, keypad);
failed_free_dev:
input_free_device(input_dev);
failed_put_clk:
clk_put(keypad->clk);
failed_free_gpio:
ep93xx_keypad_release_gpio(pdev);
failed_free_io:
iounmap(keypad->mmio_base);
failed_free_mem:
release_mem_region(res->start, resource_size(res));
failed_free:
kfree(keypad);
return err;
} }
static int ep93xx_keypad_remove(struct platform_device *pdev) static int ep93xx_keypad_remove(struct platform_device *pdev)
{ {
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); dev_pm_clear_wake_irq(&pdev->dev);
struct resource *res;
free_irq(keypad->irq, keypad);
if (keypad->enabled)
clk_disable(keypad->clk);
clk_put(keypad->clk);
input_unregister_device(keypad->input_dev);
ep93xx_keypad_release_gpio(pdev);
iounmap(keypad->mmio_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
kfree(keypad);
return 0; return 0;
} }
......
...@@ -107,9 +107,9 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev) ...@@ -107,9 +107,9 @@ static struct regulator *mpr121_vdd_supply_init(struct device *dev)
return ERR_PTR(err); return ERR_PTR(err);
} }
err = devm_add_action(dev, mpr121_vdd_supply_disable, vdd_supply); err = devm_add_action_or_reset(dev, mpr121_vdd_supply_disable,
vdd_supply);
if (err) { if (err) {
regulator_disable(vdd_supply);
dev_err(dev, "failed to add disable regulator action: %d\n", dev_err(dev, "failed to add disable regulator action: %d\n",
err); err);
return ERR_PTR(err); return ERR_PTR(err);
......
...@@ -190,8 +190,7 @@ static int omap_kp_probe(struct platform_device *pdev) ...@@ -190,8 +190,7 @@ static int omap_kp_probe(struct platform_device *pdev)
row_shift = get_count_order(pdata->cols); row_shift = get_count_order(pdata->cols);
keycodemax = pdata->rows << row_shift; keycodemax = pdata->rows << row_shift;
omap_kp = kzalloc(sizeof(struct omap_kp) + omap_kp = kzalloc(struct_size(omap_kp, keymap, keycodemax), GFP_KERNEL);
keycodemax * sizeof(unsigned short), GFP_KERNEL);
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!omap_kp || !input_dev) { if (!omap_kp || !input_dev) {
kfree(omap_kp); kfree(omap_kp);
......
...@@ -156,6 +156,8 @@ static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid) ...@@ -156,6 +156,8 @@ static irqreturn_t tm2_touchkey_irq_handler(int irq, void *devid)
goto out; goto out;
} }
input_event(touchkey->input_dev, EV_MSC, MSC_SCAN, index);
if (data & TM2_TOUCHKEY_BIT_PRESS_EV) { if (data & TM2_TOUCHKEY_BIT_PRESS_EV) {
for (i = 0; i < touchkey->num_keycodes; i++) for (i = 0; i < touchkey->num_keycodes; i++)
input_report_key(touchkey->input_dev, input_report_key(touchkey->input_dev,
...@@ -250,6 +252,11 @@ static int tm2_touchkey_probe(struct i2c_client *client, ...@@ -250,6 +252,11 @@ static int tm2_touchkey_probe(struct i2c_client *client,
touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME; touchkey->input_dev->name = TM2_TOUCHKEY_DEV_NAME;
touchkey->input_dev->id.bustype = BUS_I2C; touchkey->input_dev->id.bustype = BUS_I2C;
touchkey->input_dev->keycode = touchkey->keycodes;
touchkey->input_dev->keycodemax = touchkey->num_keycodes;
touchkey->input_dev->keycodesize = sizeof(touchkey->keycodes[0]);
input_set_capability(touchkey->input_dev, EV_MSC, MSC_SCAN);
for (i = 0; i < touchkey->num_keycodes; i++) for (i = 0; i < touchkey->num_keycodes; i++)
input_set_capability(touchkey->input_dev, EV_KEY, input_set_capability(touchkey->input_dev, EV_KEY,
touchkey->keycodes[i]); touchkey->keycodes[i]);
......
...@@ -103,7 +103,9 @@ static int adxl34x_i2c_remove(struct i2c_client *client) ...@@ -103,7 +103,9 @@ static int adxl34x_i2c_remove(struct i2c_client *client)
{ {
struct adxl34x *ac = i2c_get_clientdata(client); struct adxl34x *ac = i2c_get_clientdata(client);
return adxl34x_remove(ac); adxl34x_remove(ac);
return 0;
} }
static int __maybe_unused adxl34x_i2c_suspend(struct device *dev) static int __maybe_unused adxl34x_i2c_suspend(struct device *dev)
......
...@@ -91,7 +91,9 @@ static int adxl34x_spi_remove(struct spi_device *spi) ...@@ -91,7 +91,9 @@ static int adxl34x_spi_remove(struct spi_device *spi)
{ {
struct adxl34x *ac = spi_get_drvdata(spi); struct adxl34x *ac = spi_get_drvdata(spi);
return adxl34x_remove(ac); adxl34x_remove(ac);
return 0;
} }
static int __maybe_unused adxl34x_spi_suspend(struct device *dev) static int __maybe_unused adxl34x_spi_suspend(struct device *dev)
......
...@@ -237,7 +237,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = { ...@@ -237,7 +237,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = {
static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis)
{ {
short buf[3]; __le16 buf[3];
ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf); ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf);
...@@ -896,15 +896,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ...@@ -896,15 +896,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
} }
EXPORT_SYMBOL_GPL(adxl34x_probe); EXPORT_SYMBOL_GPL(adxl34x_probe);
int adxl34x_remove(struct adxl34x *ac) void adxl34x_remove(struct adxl34x *ac)
{ {
sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group);
free_irq(ac->irq, ac); free_irq(ac->irq, ac);
input_unregister_device(ac->input); input_unregister_device(ac->input);
dev_dbg(ac->dev, "unregistered accelerometer\n"); dev_dbg(ac->dev, "unregistered accelerometer\n");
kfree(ac); kfree(ac);
return 0;
} }
EXPORT_SYMBOL_GPL(adxl34x_remove); EXPORT_SYMBOL_GPL(adxl34x_remove);
......
...@@ -25,6 +25,6 @@ void adxl34x_resume(struct adxl34x *ac); ...@@ -25,6 +25,6 @@ void adxl34x_resume(struct adxl34x *ac);
struct adxl34x *adxl34x_probe(struct device *dev, int irq, struct adxl34x *adxl34x_probe(struct device *dev, int irq,
bool fifo_delay_default, bool fifo_delay_default,
const struct adxl34x_bus_ops *bops); const struct adxl34x_bus_ops *bops);
int adxl34x_remove(struct adxl34x *ac); void adxl34x_remove(struct adxl34x *ac);
#endif #endif
...@@ -149,12 +149,19 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = { ...@@ -149,12 +149,19 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match); MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match);
static const struct spi_device_id ariel_pwrbutton_spi_ids[] = {
{ .name = "wyse-ariel-ec-input" },
{ }
};
MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_spi_ids);
static struct spi_driver ariel_pwrbutton_driver = { static struct spi_driver ariel_pwrbutton_driver = {
.driver = { .driver = {
.name = "dell-wyse-ariel-ec-input", .name = "dell-wyse-ariel-ec-input",
.of_match_table = ariel_pwrbutton_of_match, .of_match_table = ariel_pwrbutton_of_match,
}, },
.probe = ariel_pwrbutton_probe, .probe = ariel_pwrbutton_probe,
.id_table = ariel_pwrbutton_spi_ids,
}; };
module_spi_driver(ariel_pwrbutton_driver); module_spi_driver(ariel_pwrbutton_driver);
......
...@@ -54,9 +54,13 @@ static irqreturn_t powerbutton_irq(int irq, void *_button) ...@@ -54,9 +54,13 @@ static irqreturn_t powerbutton_irq(int irq, void *_button)
static int cpcap_power_button_probe(struct platform_device *pdev) static int cpcap_power_button_probe(struct platform_device *pdev)
{ {
struct cpcap_power_button *button; struct cpcap_power_button *button;
int irq = platform_get_irq(pdev, 0); int irq;
int err; int err;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
button = devm_kmalloc(&pdev->dev, sizeof(*button), GFP_KERNEL); button = devm_kmalloc(&pdev->dev, sizeof(*button), GFP_KERNEL);
if (!button) if (!button)
return -ENOMEM; return -ENOMEM;
...@@ -73,7 +77,6 @@ static int cpcap_power_button_probe(struct platform_device *pdev) ...@@ -73,7 +77,6 @@ static int cpcap_power_button_probe(struct platform_device *pdev)
button->idev->name = "cpcap-pwrbutton"; button->idev->name = "cpcap-pwrbutton";
button->idev->phys = "cpcap-pwrbutton/input0"; button->idev->phys = "cpcap-pwrbutton/input0";
button->idev->dev.parent = button->dev;
input_set_capability(button->idev, EV_KEY, KEY_POWER); input_set_capability(button->idev, EV_KEY, KEY_POWER);
err = devm_request_threaded_irq(&pdev->dev, irq, NULL, err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
......
...@@ -424,5 +424,4 @@ module_platform_driver(max77693_haptic_driver); ...@@ -424,5 +424,4 @@ module_platform_driver(max77693_haptic_driver);
MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver"); MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver");
MODULE_ALIAS("platform:max77693-haptic");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/** /*
* MAX8925 ONKEY driver * MAX8925 ONKEY driver
* *
* Copyright (C) 2009 Marvell International Ltd. * Copyright (C) 2009 Marvell International Ltd.
......
...@@ -210,6 +210,11 @@ static int palmas_pwron_probe(struct platform_device *pdev) ...@@ -210,6 +210,11 @@ static int palmas_pwron_probe(struct platform_device *pdev)
INIT_DELAYED_WORK(&pwron->input_work, palmas_power_button_work); INIT_DELAYED_WORK(&pwron->input_work, palmas_power_button_work);
pwron->irq = platform_get_irq(pdev, 0); pwron->irq = platform_get_irq(pdev, 0);
if (pwron->irq < 0) {
error = pwron->irq;
goto err_free_input;
}
error = request_threaded_irq(pwron->irq, NULL, pwron_irq, error = request_threaded_irq(pwron->irq, NULL, pwron_irq,
IRQF_TRIGGER_HIGH | IRQF_TRIGGER_HIGH |
IRQF_TRIGGER_LOW | IRQF_TRIGGER_LOW |
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define PON_PS_HOLD_RST_CTL2 0x5b #define PON_PS_HOLD_RST_CTL2 0x5b
#define PON_PS_HOLD_ENABLE BIT(7) #define PON_PS_HOLD_ENABLE BIT(7)
#define PON_PS_HOLD_TYPE_MASK 0x0f #define PON_PS_HOLD_TYPE_MASK 0x0f
#define PON_PS_HOLD_TYPE_WARM_RESET 1
#define PON_PS_HOLD_TYPE_SHUTDOWN 4 #define PON_PS_HOLD_TYPE_SHUTDOWN 4
#define PON_PS_HOLD_TYPE_HARD_RESET 7 #define PON_PS_HOLD_TYPE_HARD_RESET 7
...@@ -99,7 +100,10 @@ static int pm8941_reboot_notify(struct notifier_block *nb, ...@@ -99,7 +100,10 @@ static int pm8941_reboot_notify(struct notifier_block *nb,
break; break;
case SYS_RESTART: case SYS_RESTART:
default: default:
reset_type = PON_PS_HOLD_TYPE_HARD_RESET; if (reboot_mode == REBOOT_WARM)
reset_type = PON_PS_HOLD_TYPE_WARM_RESET;
else
reset_type = PON_PS_HOLD_TYPE_HARD_RESET;
break; break;
} }
......
...@@ -517,6 +517,19 @@ static void elantech_report_trackpoint(struct psmouse *psmouse, ...@@ -517,6 +517,19 @@ static void elantech_report_trackpoint(struct psmouse *psmouse,
case 0x16008020U: case 0x16008020U:
case 0x26800010U: case 0x26800010U:
case 0x36808000U: case 0x36808000U:
/*
* This firmware misreport coordinates for trackpoint
* occasionally. Discard packets outside of [-127, 127] range
* to prevent cursor jumps.
*/
if (packet[4] == 0x80 || packet[5] == 0x80 ||
packet[1] >> 7 == packet[4] >> 7 ||
packet[2] >> 7 == packet[5] >> 7) {
elantech_debug("discarding packet [%6ph]\n", packet);
break;
}
x = packet[4] - (int)((packet[1]^0x80) << 1); x = packet[4] - (int)((packet[1]^0x80) << 1);
y = (int)((packet[2]^0x80) << 1) - packet[5]; y = (int)((packet[2]^0x80) << 1) - packet[5];
......
...@@ -90,6 +90,7 @@ int rmi_register_transport_device(struct rmi_transport_dev *xport) ...@@ -90,6 +90,7 @@ int rmi_register_transport_device(struct rmi_transport_dev *xport)
rmi_dev->dev.bus = &rmi_bus_type; rmi_dev->dev.bus = &rmi_bus_type;
rmi_dev->dev.type = &rmi_device_type; rmi_dev->dev.type = &rmi_device_type;
rmi_dev->dev.parent = xport->dev;
xport->rmi_dev = rmi_dev; xport->rmi_dev = rmi_dev;
......
...@@ -272,6 +272,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { ...@@ -272,6 +272,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
}, },
}, },
{
/* Fujitsu Lifebook T725 laptop */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
},
},
{ {
/* Fujitsu Lifebook U745 */ /* Fujitsu Lifebook U745 */
.matches = { .matches = {
...@@ -840,6 +847,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { ...@@ -840,6 +847,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"), DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
}, },
}, },
{
/* Fujitsu Lifebook T725 laptop */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
},
},
{ {
/* Fujitsu U574 laptop */ /* Fujitsu U574 laptop */
/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */ /* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
......
...@@ -425,6 +425,7 @@ config TOUCHSCREEN_HYCON_HY46XX ...@@ -425,6 +425,7 @@ config TOUCHSCREEN_HYCON_HY46XX
config TOUCHSCREEN_ILI210X config TOUCHSCREEN_ILI210X
tristate "Ilitek ILI210X based touchscreen" tristate "Ilitek ILI210X based touchscreen"
depends on I2C depends on I2C
select CRC_CCITT
help help
Say Y here if you have a ILI210X based touchscreen Say Y here if you have a ILI210X based touchscreen
controller. This driver supports models ILI2102, controller. This driver supports models ILI2102,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
wm97xx-ts-y := wm97xx-core.o wm97xx-ts-y := wm97xx-core.o
goodix_ts-y := goodix.o goodix_fwupload.o
obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
...@@ -44,7 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o ...@@ -44,7 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix_ts.o
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o obj-$(CONFIG_TOUCHSCREEN_ILITEK) += ilitek_ts_i2c.o
......
...@@ -101,10 +101,6 @@ struct ads7846 { ...@@ -101,10 +101,6 @@ struct ads7846 {
struct spi_device *spi; struct spi_device *spi;
struct regulator *reg; struct regulator *reg;
#if IS_ENABLED(CONFIG_HWMON)
struct device *hwmon;
#endif
u16 model; u16 model;
u16 vref_mv; u16 vref_mv;
u16 vref_delay_usecs; u16 vref_delay_usecs;
...@@ -142,13 +138,18 @@ struct ads7846 { ...@@ -142,13 +138,18 @@ struct ads7846 {
int (*filter)(void *data, int data_idx, int *val); int (*filter)(void *data, int data_idx, int *val);
void *filter_data; void *filter_data;
void (*filter_cleanup)(void *data);
int (*get_pendown_state)(void); int (*get_pendown_state)(void);
int gpio_pendown; int gpio_pendown;
void (*wait_for_sync)(void); void (*wait_for_sync)(void);
}; };
enum ads7846_filter {
ADS7846_FILTER_OK,
ADS7846_FILTER_REPEAT,
ADS7846_FILTER_IGNORE,
};
/* leave chip selected when we're done, for quicker re-select? */ /* leave chip selected when we're done, for quicker re-select? */
#if 0 #if 0
#define CS_CHANGE(xfer) ((xfer).cs_change = 1) #define CS_CHANGE(xfer) ((xfer).cs_change = 1)
...@@ -549,6 +550,8 @@ __ATTRIBUTE_GROUPS(ads7846_attr); ...@@ -549,6 +550,8 @@ __ATTRIBUTE_GROUPS(ads7846_attr);
static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
{ {
struct device *hwmon;
/* hwmon sensors need a reference voltage */ /* hwmon sensors need a reference voltage */
switch (ts->model) { switch (ts->model) {
case 7846: case 7846:
...@@ -569,17 +572,11 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) ...@@ -569,17 +572,11 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
break; break;
} }
ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias, hwmon = devm_hwmon_device_register_with_groups(&spi->dev,
ts, ads7846_attr_groups); spi->modalias, ts,
ads7846_attr_groups);
return PTR_ERR_OR_ZERO(ts->hwmon); return PTR_ERR_OR_ZERO(hwmon);
}
static void ads784x_hwmon_unregister(struct spi_device *spi,
struct ads7846 *ts)
{
if (ts->hwmon)
hwmon_device_unregister(ts->hwmon);
} }
#else #else
...@@ -588,11 +585,6 @@ static inline int ads784x_hwmon_register(struct spi_device *spi, ...@@ -588,11 +585,6 @@ static inline int ads784x_hwmon_register(struct spi_device *spi,
{ {
return 0; return 0;
} }
static inline void ads784x_hwmon_unregister(struct spi_device *spi,
struct ads7846 *ts)
{
}
#endif #endif
static ssize_t ads7846_pen_down_show(struct device *dev, static ssize_t ads7846_pen_down_show(struct device *dev,
...@@ -1014,8 +1006,8 @@ static int ads7846_setup_pendown(struct spi_device *spi, ...@@ -1014,8 +1006,8 @@ static int ads7846_setup_pendown(struct spi_device *spi,
ts->get_pendown_state = pdata->get_pendown_state; ts->get_pendown_state = pdata->get_pendown_state;
} else if (gpio_is_valid(pdata->gpio_pendown)) { } else if (gpio_is_valid(pdata->gpio_pendown)) {
err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN, err = devm_gpio_request_one(&spi->dev, pdata->gpio_pendown,
"ads7846_pendown"); GPIOF_IN, "ads7846_pendown");
if (err) { if (err) {
dev_err(&spi->dev, dev_err(&spi->dev,
"failed to request/setup pendown GPIO%d: %d\n", "failed to request/setup pendown GPIO%d: %d\n",
...@@ -1212,24 +1204,30 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev) ...@@ -1212,24 +1204,30 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
} }
#endif #endif
static void ads7846_regulator_disable(void *regulator)
{
regulator_disable(regulator);
}
static int ads7846_probe(struct spi_device *spi) static int ads7846_probe(struct spi_device *spi)
{ {
const struct ads7846_platform_data *pdata; const struct ads7846_platform_data *pdata;
struct ads7846 *ts; struct ads7846 *ts;
struct device *dev = &spi->dev;
struct ads7846_packet *packet; struct ads7846_packet *packet;
struct input_dev *input_dev; struct input_dev *input_dev;
unsigned long irq_flags; unsigned long irq_flags;
int err; int err;
if (!spi->irq) { if (!spi->irq) {
dev_dbg(&spi->dev, "no IRQ?\n"); dev_dbg(dev, "no IRQ?\n");
return -EINVAL; return -EINVAL;
} }
/* don't exceed max specified sample rate */ /* don't exceed max specified sample rate */
if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
dev_err(&spi->dev, "f(sample) %d KHz?\n", dev_err(dev, "f(sample) %d KHz?\n",
(spi->max_speed_hz/SAMPLE_BITS)/1000); (spi->max_speed_hz/SAMPLE_BITS)/1000);
return -EINVAL; return -EINVAL;
} }
...@@ -1245,13 +1243,17 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1245,13 +1243,17 @@ static int ads7846_probe(struct spi_device *spi)
if (err < 0) if (err < 0)
return err; return err;
ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); ts = devm_kzalloc(dev, sizeof(struct ads7846), GFP_KERNEL);
packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL); if (!ts)
input_dev = input_allocate_device(); return -ENOMEM;
if (!ts || !packet || !input_dev) {
err = -ENOMEM; packet = devm_kzalloc(dev, sizeof(struct ads7846_packet), GFP_KERNEL);
goto err_free_mem; if (!packet)
} return -ENOMEM;
input_dev = devm_input_allocate_device(dev);
if (!input_dev)
return -ENOMEM;
spi_set_drvdata(spi, ts); spi_set_drvdata(spi, ts);
...@@ -1262,13 +1264,11 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1262,13 +1264,11 @@ static int ads7846_probe(struct spi_device *spi)
mutex_init(&ts->lock); mutex_init(&ts->lock);
init_waitqueue_head(&ts->wait); init_waitqueue_head(&ts->wait);
pdata = dev_get_platdata(&spi->dev); pdata = dev_get_platdata(dev);
if (!pdata) { if (!pdata) {
pdata = ads7846_probe_dt(&spi->dev); pdata = ads7846_probe_dt(dev);
if (IS_ERR(pdata)) { if (IS_ERR(pdata))
err = PTR_ERR(pdata); return PTR_ERR(pdata);
goto err_free_mem;
}
} }
ts->model = pdata->model ? : 7846; ts->model = pdata->model ? : 7846;
...@@ -1276,15 +1276,7 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1276,15 +1276,7 @@ static int ads7846_probe(struct spi_device *spi)
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
ts->vref_mv = pdata->vref_mv; ts->vref_mv = pdata->vref_mv;
if (pdata->filter != NULL) { if (pdata->debounce_max) {
if (pdata->filter_init != NULL) {
err = pdata->filter_init(pdata, &ts->filter_data);
if (err < 0)
goto err_free_mem;
}
ts->filter = pdata->filter;
ts->filter_cleanup = pdata->filter_cleanup;
} else if (pdata->debounce_max) {
ts->debounce_max = pdata->debounce_max; ts->debounce_max = pdata->debounce_max;
if (ts->debounce_max < 2) if (ts->debounce_max < 2)
ts->debounce_max = 2; ts->debounce_max = 2;
...@@ -1298,7 +1290,7 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1298,7 +1290,7 @@ static int ads7846_probe(struct spi_device *spi)
err = ads7846_setup_pendown(spi, ts, pdata); err = ads7846_setup_pendown(spi, ts, pdata);
if (err) if (err)
goto err_cleanup_filter; return err;
if (pdata->penirq_recheck_delay_usecs) if (pdata->penirq_recheck_delay_usecs)
ts->penirq_recheck_delay_usecs = ts->penirq_recheck_delay_usecs =
...@@ -1306,15 +1298,16 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1306,15 +1298,16 @@ static int ads7846_probe(struct spi_device *spi)
ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model); snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
input_dev->name = ts->name; input_dev->name = ts->name;
input_dev->phys = ts->phys; input_dev->phys = ts->phys;
input_dev->dev.parent = &spi->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->id.bustype = BUS_SPI;
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_dev->id.product = pdata->model;
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, input_set_abs_params(input_dev, ABS_X,
pdata->x_min ? : 0, pdata->x_min ? : 0,
pdata->x_max ? : MAX_12BIT, pdata->x_max ? : MAX_12BIT,
...@@ -1345,125 +1338,84 @@ static int ads7846_probe(struct spi_device *spi) ...@@ -1345,125 +1338,84 @@ static int ads7846_probe(struct spi_device *spi)
ads7846_setup_spi_msg(ts, pdata); ads7846_setup_spi_msg(ts, pdata);
ts->reg = regulator_get(&spi->dev, "vcc"); ts->reg = devm_regulator_get(dev, "vcc");
if (IS_ERR(ts->reg)) { if (IS_ERR(ts->reg)) {
err = PTR_ERR(ts->reg); err = PTR_ERR(ts->reg);
dev_err(&spi->dev, "unable to get regulator: %d\n", err); dev_err(dev, "unable to get regulator: %d\n", err);
goto err_free_gpio; return err;
} }
err = regulator_enable(ts->reg); err = regulator_enable(ts->reg);
if (err) { if (err) {
dev_err(&spi->dev, "unable to enable regulator: %d\n", err); dev_err(dev, "unable to enable regulator: %d\n", err);
goto err_put_regulator; return err;
} }
err = devm_add_action_or_reset(dev, ads7846_regulator_disable, ts->reg);
if (err)
return err;
irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING; irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
irq_flags |= IRQF_ONESHOT; irq_flags |= IRQF_ONESHOT;
err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq, err = devm_request_threaded_irq(dev, spi->irq,
irq_flags, spi->dev.driver->name, ts); ads7846_hard_irq, ads7846_irq,
if (err && !pdata->irq_flags) { irq_flags, dev->driver->name, ts);
dev_info(&spi->dev, if (err && err != -EPROBE_DEFER && !pdata->irq_flags) {
dev_info(dev,
"trying pin change workaround on irq %d\n", spi->irq); "trying pin change workaround on irq %d\n", spi->irq);
irq_flags |= IRQF_TRIGGER_RISING; irq_flags |= IRQF_TRIGGER_RISING;
err = request_threaded_irq(spi->irq, err = devm_request_threaded_irq(dev, spi->irq,
ads7846_hard_irq, ads7846_irq, ads7846_hard_irq, ads7846_irq,
irq_flags, spi->dev.driver->name, ts); irq_flags, dev->driver->name,
ts);
} }
if (err) { if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); dev_dbg(dev, "irq %d busy?\n", spi->irq);
goto err_disable_regulator; return err;
} }
err = ads784x_hwmon_register(spi, ts); err = ads784x_hwmon_register(spi, ts);
if (err) if (err)
goto err_free_irq; return err;
dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); dev_info(dev, "touchscreen, irq %d\n", spi->irq);
/* /*
* Take a first sample, leaving nPENIRQ active and vREF off; avoid * Take a first sample, leaving nPENIRQ active and vREF off; avoid
* the touchscreen, in case it's not connected. * the touchscreen, in case it's not connected.
*/ */
if (ts->model == 7845) if (ts->model == 7845)
ads7845_read12_ser(&spi->dev, PWRDOWN); ads7845_read12_ser(dev, PWRDOWN);
else else
(void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux)); (void) ads7846_read12_ser(dev, READ_12BIT_SER(vaux));
err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); err = devm_device_add_group(dev, &ads784x_attr_group);
if (err) if (err)
goto err_remove_hwmon; return err;
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) if (err)
goto err_remove_attr_group; return err;
device_init_wakeup(&spi->dev, pdata->wakeup); device_init_wakeup(dev, pdata->wakeup);
/* /*
* If device does not carry platform data we must have allocated it * If device does not carry platform data we must have allocated it
* when parsing DT data. * when parsing DT data.
*/ */
if (!dev_get_platdata(&spi->dev)) if (!dev_get_platdata(dev))
devm_kfree(&spi->dev, (void *)pdata); devm_kfree(dev, (void *)pdata);
return 0; return 0;
err_remove_attr_group:
sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
err_remove_hwmon:
ads784x_hwmon_unregister(spi, ts);
err_free_irq:
free_irq(spi->irq, ts);
err_disable_regulator:
regulator_disable(ts->reg);
err_put_regulator:
regulator_put(ts->reg);
err_free_gpio:
if (!ts->get_pendown_state)
gpio_free(ts->gpio_pendown);
err_cleanup_filter:
if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);
err_free_mem:
input_free_device(input_dev);
kfree(packet);
kfree(ts);
return err;
} }
static int ads7846_remove(struct spi_device *spi) static int ads7846_remove(struct spi_device *spi)
{ {
struct ads7846 *ts = spi_get_drvdata(spi); struct ads7846 *ts = spi_get_drvdata(spi);
sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); ads7846_stop(ts);
ads7846_disable(ts);
free_irq(ts->spi->irq, ts);
input_unregister_device(ts->input);
ads784x_hwmon_unregister(spi, ts);
regulator_put(ts->reg);
if (!ts->get_pendown_state) {
/*
* If we are not using specialized pendown method we must
* have been relying on gpio we set up ourselves.
*/
gpio_free(ts->gpio_pendown);
}
if (ts->filter_cleanup)
ts->filter_cleanup(ts->filter_data);
kfree(ts->packet);
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
return 0; return 0;
} }
......
...@@ -1439,11 +1439,11 @@ static int elants_i2c_probe(struct i2c_client *client) ...@@ -1439,11 +1439,11 @@ static int elants_i2c_probe(struct i2c_client *client)
if (error) if (error)
return error; return error;
error = devm_add_action(&client->dev, elants_i2c_power_off, ts); error = devm_add_action_or_reset(&client->dev,
elants_i2c_power_off, ts);
if (error) { if (error) {
dev_err(&client->dev, dev_err(&client->dev,
"failed to install power off action: %d\n", error); "failed to install power off action: %d\n", error);
elants_i2c_power_off(ts);
return error; return error;
} }
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __GOODIX_H__
#define __GOODIX_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/regulator/consumer.h>
/* Register defines */
#define GOODIX_REG_MISCTL_DSP_CTL 0x4010
#define GOODIX_REG_MISCTL_SRAM_BANK 0x4048
#define GOODIX_REG_MISCTL_MEM_CD_EN 0x4049
#define GOODIX_REG_MISCTL_CACHE_EN 0x404B
#define GOODIX_REG_MISCTL_TMR0_EN 0x40B0
#define GOODIX_REG_MISCTL_SWRST 0x4180
#define GOODIX_REG_MISCTL_CPU_SWRST_PULSE 0x4184
#define GOODIX_REG_MISCTL_BOOTCTL 0x4190
#define GOODIX_REG_MISCTL_BOOT_OPT 0x4218
#define GOODIX_REG_MISCTL_BOOT_CTL 0x5094
#define GOODIX_REG_FW_SIG 0x8000
#define GOODIX_FW_SIG_LEN 10
#define GOODIX_REG_MAIN_CLK 0x8020
#define GOODIX_MAIN_CLK_LEN 6
#define GOODIX_REG_COMMAND 0x8040
#define GOODIX_CMD_SCREEN_OFF 0x05
#define GOODIX_REG_SW_WDT 0x8041
#define GOODIX_REG_REQUEST 0x8043
#define GOODIX_RQST_RESPONDED 0x00
#define GOODIX_RQST_CONFIG 0x01
#define GOODIX_RQST_BAK_REF 0x02
#define GOODIX_RQST_RESET 0x03
#define GOODIX_RQST_MAIN_CLOCK 0x04
/*
* Unknown request which gets send by the controller aprox.
* every 34 seconds once it is up and running.
*/
#define GOODIX_RQST_UNKNOWN 0x06
#define GOODIX_RQST_IDLE 0xFF
#define GOODIX_REG_STATUS 0x8044
#define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
#define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
#define GOODIX_REG_ID 0x8140
#define GOODIX_READ_COOR_ADDR 0x814E
#define GOODIX_REG_BAK_REF 0x99D0
#define GOODIX_ID_MAX_LEN 4
#define GOODIX_CONFIG_MAX_LENGTH 240
#define GOODIX_MAX_KEYS 7
enum goodix_irq_pin_access_method {
IRQ_PIN_ACCESS_NONE,
IRQ_PIN_ACCESS_GPIO,
IRQ_PIN_ACCESS_ACPI_GPIO,
IRQ_PIN_ACCESS_ACPI_METHOD,
};
struct goodix_ts_data;
struct goodix_chip_data {
u16 config_addr;
int config_len;
int (*check_config)(struct goodix_ts_data *ts, const u8 *cfg, int len);
void (*calc_config_checksum)(struct goodix_ts_data *ts);
};
struct goodix_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
const struct goodix_chip_data *chip;
const char *firmware_name;
struct touchscreen_properties prop;
unsigned int max_touch_num;
unsigned int int_trigger_type;
struct regulator *avdd28;
struct regulator *vddio;
struct gpio_desc *gpiod_int;
struct gpio_desc *gpiod_rst;
int gpio_count;
int gpio_int_idx;
char id[GOODIX_ID_MAX_LEN + 1];
char cfg_name[64];
u16 version;
bool reset_controller_at_probe;
bool load_cfg_from_disk;
struct completion firmware_loading_complete;
unsigned long irq_flags;
enum goodix_irq_pin_access_method irq_pin_access_method;
unsigned int contact_size;
u8 config[GOODIX_CONFIG_MAX_LENGTH];
unsigned short keymap[GOODIX_MAX_KEYS];
u8 main_clk[GOODIX_MAIN_CLK_LEN];
int bak_ref_len;
u8 *bak_ref;
};
int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len);
int goodix_i2c_write(struct i2c_client *client, u16 reg, const u8 *buf, int len);
int goodix_i2c_write_u8(struct i2c_client *client, u16 reg, u8 value);
int goodix_send_cfg(struct goodix_ts_data *ts, const u8 *cfg, int len);
int goodix_int_sync(struct goodix_ts_data *ts);
int goodix_reset_no_int_sync(struct goodix_ts_data *ts);
int goodix_firmware_check(struct goodix_ts_data *ts);
bool goodix_handle_fw_request(struct goodix_ts_data *ts);
void goodix_save_bak_ref(struct goodix_ts_data *ts);
#endif
This diff is collapsed.
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#define RM_CMD_BOOT_READ 0x44 /* send wait bl data ready*/ #define RM_CMD_BOOT_READ 0x44 /* send wait bl data ready*/
#define RM_BOOT_RDY 0xFF /* bl data ready */ #define RM_BOOT_RDY 0xFF /* bl data ready */
#define RM_BOOT_CMD_READHWID 0x0E /* read hwid */
/* I2C main commands */ /* I2C main commands */
#define RM_CMD_QUERY_BANK 0x2B #define RM_CMD_QUERY_BANK 0x2B
...@@ -290,6 +291,44 @@ static int raydium_i2c_sw_reset(struct i2c_client *client) ...@@ -290,6 +291,44 @@ static int raydium_i2c_sw_reset(struct i2c_client *client)
return 0; return 0;
} }
static int raydium_i2c_query_ts_bootloader_info(struct raydium_data *ts)
{
struct i2c_client *client = ts->client;
static const u8 get_hwid[] = { RM_BOOT_CMD_READHWID,
0x10, 0xc0, 0x01, 0x00, 0x04, 0x00 };
u8 rbuf[5] = { 0 };
u32 hw_ver;
int error;
error = raydium_i2c_send(client, RM_CMD_BOOT_WRT,
get_hwid, sizeof(get_hwid));
if (error) {
dev_err(&client->dev, "WRT HWID command failed: %d\n", error);
return error;
}
error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, rbuf, 1);
if (error) {
dev_err(&client->dev, "Ack HWID command failed: %d\n", error);
return error;
}
error = raydium_i2c_read(client, RM_CMD_BOOT_CHK, rbuf, sizeof(rbuf));
if (error) {
dev_err(&client->dev, "Read HWID command failed: %d (%4ph)\n",
error, rbuf + 1);
hw_ver = 0xffffffffUL;
} else {
hw_ver = get_unaligned_be32(rbuf + 1);
}
ts->info.hw_ver = cpu_to_le32(hw_ver);
ts->info.main_ver = 0xff;
ts->info.sub_ver = 0xff;
return error;
}
static int raydium_i2c_query_ts_info(struct raydium_data *ts) static int raydium_i2c_query_ts_info(struct raydium_data *ts)
{ {
struct i2c_client *client = ts->client; struct i2c_client *client = ts->client;
...@@ -388,13 +427,10 @@ static int raydium_i2c_initialize(struct raydium_data *ts) ...@@ -388,13 +427,10 @@ static int raydium_i2c_initialize(struct raydium_data *ts)
if (error) if (error)
ts->boot_mode = RAYDIUM_TS_BLDR; ts->boot_mode = RAYDIUM_TS_BLDR;
if (ts->boot_mode == RAYDIUM_TS_BLDR) { if (ts->boot_mode == RAYDIUM_TS_BLDR)
ts->info.hw_ver = cpu_to_le32(0xffffffffUL); raydium_i2c_query_ts_bootloader_info(ts);
ts->info.main_ver = 0xff; else
ts->info.sub_ver = 0xff;
} else {
raydium_i2c_query_ts_info(ts); raydium_i2c_query_ts_info(ts);
}
return error; return error;
} }
...@@ -1082,11 +1118,11 @@ static int raydium_i2c_probe(struct i2c_client *client, ...@@ -1082,11 +1118,11 @@ static int raydium_i2c_probe(struct i2c_client *client,
if (error) if (error)
return error; return error;
error = devm_add_action(&client->dev, raydium_i2c_power_off, ts); error = devm_add_action_or_reset(&client->dev,
raydium_i2c_power_off, ts);
if (error) { if (error) {
dev_err(&client->dev, dev_err(&client->dev,
"failed to install power off action: %d\n", error); "failed to install power off action: %d\n", error);
raydium_i2c_power_off(ts);
return error; return error;
} }
...@@ -1218,7 +1254,7 @@ static SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops, ...@@ -1218,7 +1254,7 @@ static SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops,
raydium_i2c_suspend, raydium_i2c_resume); raydium_i2c_suspend, raydium_i2c_resume);
static const struct i2c_device_id raydium_i2c_id[] = { static const struct i2c_device_id raydium_i2c_id[] = {
{ "raydium_i2c" , 0 }, { "raydium_i2c", 0 },
{ "rm32380", 0 }, { "rm32380", 0 },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -92,7 +92,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts) ...@@ -92,7 +92,7 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
unsigned int retries; unsigned int retries;
int error; int error;
for (retries = 10; retries; retries--) { for (retries = 100; retries; retries--) {
error = st1232_ts_read_data(ts, REG_STATUS, 1); error = st1232_ts_read_data(ts, REG_STATUS, 1);
if (!error) { if (!error) {
switch (ts->read_buf[0]) { switch (ts->read_buf[0]) {
...@@ -389,6 +389,7 @@ static struct i2c_driver st1232_ts_driver = { ...@@ -389,6 +389,7 @@ static struct i2c_driver st1232_ts_driver = {
.driver = { .driver = {
.name = ST1232_TS_NAME, .name = ST1232_TS_NAME,
.of_match_table = st1232_ts_dt_ids, .of_match_table = st1232_ts_dt_ids,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = &st1232_ts_pm_ops, .pm = &st1232_ts_pm_ops,
}, },
}; };
......
...@@ -45,7 +45,9 @@ static int tsc2004_probe(struct i2c_client *i2c, ...@@ -45,7 +45,9 @@ static int tsc2004_probe(struct i2c_client *i2c,
static int tsc2004_remove(struct i2c_client *i2c) static int tsc2004_remove(struct i2c_client *i2c)
{ {
return tsc200x_remove(&i2c->dev); tsc200x_remove(&i2c->dev);
return 0;
} }
static const struct i2c_device_id tsc2004_idtable[] = { static const struct i2c_device_id tsc2004_idtable[] = {
......
...@@ -66,7 +66,9 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -66,7 +66,9 @@ static int tsc2005_probe(struct spi_device *spi)
static int tsc2005_remove(struct spi_device *spi) static int tsc2005_remove(struct spi_device *spi)
{ {
return tsc200x_remove(&spi->dev); tsc200x_remove(&spi->dev);
return 0;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -577,15 +577,13 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, ...@@ -577,15 +577,13 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
} }
EXPORT_SYMBOL_GPL(tsc200x_probe); EXPORT_SYMBOL_GPL(tsc200x_probe);
int tsc200x_remove(struct device *dev) void tsc200x_remove(struct device *dev)
{ {
struct tsc200x *ts = dev_get_drvdata(dev); struct tsc200x *ts = dev_get_drvdata(dev);
sysfs_remove_group(&dev->kobj, &tsc200x_attr_group); sysfs_remove_group(&dev->kobj, &tsc200x_attr_group);
regulator_disable(ts->vio); regulator_disable(ts->vio);
return 0;
} }
EXPORT_SYMBOL_GPL(tsc200x_remove); EXPORT_SYMBOL_GPL(tsc200x_remove);
......
...@@ -74,6 +74,6 @@ extern const struct dev_pm_ops tsc200x_pm_ops; ...@@ -74,6 +74,6 @@ extern const struct dev_pm_ops tsc200x_pm_ops;
int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id,
struct regmap *regmap, struct regmap *regmap,
int (*tsc200x_cmd)(struct device *dev, u8 cmd)); int (*tsc200x_cmd)(struct device *dev, u8 cmd));
int tsc200x_remove(struct device *dev); void tsc200x_remove(struct device *dev);
#endif #endif
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* <tobita.tatsunosuke@wacom.co.jp> * <tobita.tatsunosuke@wacom.co.jp>
*/ */
#include <linux/bits.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -14,6 +15,15 @@ ...@@ -14,6 +15,15 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
/* Bitmasks (for data[3]) */
#define WACOM_TIP_SWITCH BIT(0)
#define WACOM_BARREL_SWITCH BIT(1)
#define WACOM_ERASER BIT(2)
#define WACOM_INVERT BIT(3)
#define WACOM_BARREL_SWITCH_2 BIT(4)
#define WACOM_IN_PROXIMITY BIT(5)
/* Registers */
#define WACOM_CMD_QUERY0 0x04 #define WACOM_CMD_QUERY0 0x04
#define WACOM_CMD_QUERY1 0x00 #define WACOM_CMD_QUERY1 0x00
#define WACOM_CMD_QUERY2 0x33 #define WACOM_CMD_QUERY2 0x33
...@@ -99,19 +109,19 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) ...@@ -99,19 +109,19 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
if (error < 0) if (error < 0)
goto out; goto out;
tsw = data[3] & 0x01; tsw = data[3] & WACOM_TIP_SWITCH;
ers = data[3] & 0x04; ers = data[3] & WACOM_ERASER;
f1 = data[3] & 0x02; f1 = data[3] & WACOM_BARREL_SWITCH;
f2 = data[3] & 0x10; f2 = data[3] & WACOM_BARREL_SWITCH_2;
x = le16_to_cpup((__le16 *)&data[4]); x = le16_to_cpup((__le16 *)&data[4]);
y = le16_to_cpup((__le16 *)&data[6]); y = le16_to_cpup((__le16 *)&data[6]);
pressure = le16_to_cpup((__le16 *)&data[8]); pressure = le16_to_cpup((__le16 *)&data[8]);
if (!wac_i2c->prox) if (!wac_i2c->prox)
wac_i2c->tool = (data[3] & 0x0c) ? wac_i2c->tool = (data[3] & (WACOM_ERASER | WACOM_INVERT)) ?
BTN_TOOL_RUBBER : BTN_TOOL_PEN; BTN_TOOL_RUBBER : BTN_TOOL_PEN;
wac_i2c->prox = data[3] & 0x20; wac_i2c->prox = data[3] & WACOM_IN_PROXIMITY;
input_report_key(input, BTN_TOUCH, tsw || ers); input_report_key(input, BTN_TOUCH, tsw || ers);
input_report_key(input, wac_i2c->tool, wac_i2c->prox); input_report_key(input, wac_i2c->tool, wac_i2c->prox);
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_CY8CTMG110_PDATA_H
#define _LINUX_CY8CTMG110_PDATA_H
struct cy8ctmg110_pdata
{
int reset_pin; /* Reset pin is wired to this GPIO (optional) */
};
#endif
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/* linux/spi/ads7846.h */ /* linux/spi/ads7846.h */
/* Touchscreen characteristics vary between boards and models. The
* platform_data for the device's "struct device" holds this information.
*
* It's OK if the min/max values are zero.
*/
enum ads7846_filter {
ADS7846_FILTER_OK,
ADS7846_FILTER_REPEAT,
ADS7846_FILTER_IGNORE,
};
struct ads7846_platform_data { struct ads7846_platform_data {
u16 model; /* 7843, 7845, 7846, 7873. */ u16 model; /* 7843, 7845, 7846, 7873. */
u16 vref_delay_usecs; /* 0 for external vref; etc */ u16 vref_delay_usecs; /* 0 for external vref; etc */
...@@ -51,10 +40,6 @@ struct ads7846_platform_data { ...@@ -51,10 +40,6 @@ struct ads7846_platform_data {
int gpio_pendown_debounce; /* platform specific debounce time for int gpio_pendown_debounce; /* platform specific debounce time for
* the gpio_pendown */ * the gpio_pendown */
int (*get_pendown_state)(void); int (*get_pendown_state)(void);
int (*filter_init) (const struct ads7846_platform_data *pdata,
void **filter_data);
int (*filter) (void *filter_data, int data_idx, int *val);
void (*filter_cleanup)(void *filter_data);
void (*wait_for_sync)(void); void (*wait_for_sync)(void);
bool wakeup; bool wakeup;
unsigned long irq_flags; unsigned long irq_flags;
......
...@@ -33,6 +33,7 @@ EXPORT_SYMBOL(cad_pid); ...@@ -33,6 +33,7 @@ EXPORT_SYMBOL(cad_pid);
#define DEFAULT_REBOOT_MODE #define DEFAULT_REBOOT_MODE
#endif #endif
enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE; enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
EXPORT_SYMBOL_GPL(reboot_mode);
enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED; enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment