aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2021-07-04 23:05:31 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2021-07-04 23:05:31 -0700
commit818b26588994d9d95743fca0a427f08ec6c1c41d (patch)
tree870d9abed0e43b82257350a93e6517816815cd6c /drivers/input
parentInput: elants_i2c - switch to probe_new (diff)
parentInput: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl (diff)
downloadlinux-dev-818b26588994d9d95743fca0a427f08ec6c1c41d.tar.xz
linux-dev-818b26588994d9d95743fca0a427f08ec6c1c41d.zip
Merge branch 'next' into for-linus
Prepare input updates for 5.14 merge window.
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/evbug.c3
-rw-r--r--drivers/input/joydev.c2
-rw-r--r--drivers/input/joystick/Kconfig9
-rw-r--r--drivers/input/joystick/Makefile1
-rw-r--r--drivers/input/joystick/qwiic-joystick.c146
-rw-r--r--drivers/input/keyboard/atkbd.c2
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c2
-rw-r--r--drivers/input/keyboard/hil_kbd.c1
-rw-r--r--drivers/input/misc/ims-pcu.c6
-rw-r--r--drivers/input/misc/pm8941-pwrkey.c103
-rw-r--r--drivers/input/mouse/trackpoint.c2
-rw-r--r--drivers/input/serio/i8042.c4
-rw-r--r--drivers/input/touchscreen/cy8ctmg110_ts.c167
-rw-r--r--drivers/input/touchscreen/cyttsp_core.c47
-rw-r--r--drivers/input/touchscreen/cyttsp_core.h3
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c10
-rw-r--r--drivers/input/touchscreen/cyttsp_spi.c10
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c38
-rw-r--r--drivers/input/touchscreen/hideep.c13
-rw-r--r--drivers/input/touchscreen/resistive-adc-touch.c136
-rw-r--r--drivers/input/touchscreen/tsc200x-core.c2
21 files changed, 522 insertions, 185 deletions
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index c0d0b121ae7e..e47bdf92088a 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -7,9 +7,6 @@
* Input driver event debug module - dumps all events into syslog
*/
-/*
- */
-
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/slab.h>
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index da8963a9f044..947d440a3be6 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -499,7 +499,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
memcpy(joydev->keypam, keypam, len);
for (i = 0; i < joydev->nkey; i++)
- joydev->keymap[keypam[i] - BTN_MISC] = i;
+ joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
out:
kfree(keypam);
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 5e38899058c1..7dfe8ea90923 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -372,6 +372,15 @@ config JOYSTICK_PXRC
To compile this driver as a module, choose M here: the
module will be called pxrc.
+config JOYSTICK_QWIIC
+ tristate "SparkFun Qwiic Joystick"
+ depends on I2C
+ help
+ Say Y here if you want to use the SparkFun Qwiic Joystick.
+
+ To compile this driver as a module, choose M here: the
+ module will be called qwiic-joystick.
+
config JOYSTICK_FSIA6B
tristate "FlySky FS-iA6B RC Receiver"
select SERIO
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
index 31d720c9e493..5174b8aba2dd 100644
--- a/drivers/input/joystick/Makefile
+++ b/drivers/input/joystick/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
+obj-$(CONFIG_JOYSTICK_QWIIC) += qwiic-joystick.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c
new file mode 100644
index 000000000000..d4da31c0616c
--- /dev/null
+++ b/drivers/input/joystick/qwiic-joystick.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Oleh Kravchenko <oleg@kaa.org.ua>
+ *
+ * SparkFun Qwiic Joystick
+ * Product page:https://www.sparkfun.com/products/15168
+ * Firmware and hardware sources:https://github.com/sparkfun/Qwiic_Joystick
+ */
+
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define DRV_NAME "qwiic-joystick"
+
+#define QWIIC_JSK_REG_VERS 1
+#define QWIIC_JSK_REG_DATA 3
+
+#define QWIIC_JSK_MAX_AXIS GENMASK(9, 0)
+#define QWIIC_JSK_FUZZ 2
+#define QWIIC_JSK_FLAT 2
+#define QWIIC_JSK_POLL_INTERVAL 16
+#define QWIIC_JSK_POLL_MIN 8
+#define QWIIC_JSK_POLL_MAX 32
+
+struct qwiic_jsk {
+ char phys[32];
+ struct input_dev *dev;
+ struct i2c_client *client;
+};
+
+struct qwiic_ver {
+ u8 major;
+ u8 minor;
+};
+
+struct qwiic_data {
+ __be16 x;
+ __be16 y;
+ u8 thumb;
+};
+
+static void qwiic_poll(struct input_dev *input)
+{
+ struct qwiic_jsk *priv = input_get_drvdata(input);
+ struct qwiic_data data;
+ int err;
+
+ err = i2c_smbus_read_i2c_block_data(priv->client, QWIIC_JSK_REG_DATA,
+ sizeof(data), (u8 *)&data);
+ if (err != sizeof(data))
+ return;
+
+ input_report_abs(input, ABS_X, be16_to_cpu(data.x) >> 6);
+ input_report_abs(input, ABS_Y, be16_to_cpu(data.y) >> 6);
+ input_report_key(input, BTN_THUMBL, !data.thumb);
+ input_sync(input);
+}
+
+static int qwiic_probe(struct i2c_client *client)
+{
+ struct qwiic_jsk *priv;
+ struct qwiic_ver vers;
+ int err;
+
+ err = i2c_smbus_read_i2c_block_data(client, QWIIC_JSK_REG_VERS,
+ sizeof(vers), (u8 *)&vers);
+ if (err < 0)
+ return err;
+ if (err != sizeof(vers))
+ return -EIO;
+
+ dev_dbg(&client->dev, "SparkFun Qwiic Joystick, FW: %u.%u\n",
+ vers.major, vers.minor);
+
+ priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->client = client;
+ snprintf(priv->phys, sizeof(priv->phys),
+ "i2c/%s", dev_name(&client->dev));
+ i2c_set_clientdata(client, priv);
+
+ priv->dev = devm_input_allocate_device(&client->dev);
+ if (!priv->dev)
+ return -ENOMEM;
+
+ priv->dev->id.bustype = BUS_I2C;
+ priv->dev->name = "SparkFun Qwiic Joystick";
+ priv->dev->phys = priv->phys;
+ input_set_drvdata(priv->dev, priv);
+
+ input_set_abs_params(priv->dev, ABS_X, 0, QWIIC_JSK_MAX_AXIS,
+ QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
+ input_set_abs_params(priv->dev, ABS_Y, 0, QWIIC_JSK_MAX_AXIS,
+ QWIIC_JSK_FUZZ, QWIIC_JSK_FLAT);
+ input_set_capability(priv->dev, EV_KEY, BTN_THUMBL);
+
+ err = input_setup_polling(priv->dev, qwiic_poll);
+ if (err) {
+ dev_err(&client->dev, "failed to set up polling: %d\n", err);
+ return err;
+ }
+ input_set_poll_interval(priv->dev, QWIIC_JSK_POLL_INTERVAL);
+ input_set_min_poll_interval(priv->dev, QWIIC_JSK_POLL_MIN);
+ input_set_max_poll_interval(priv->dev, QWIIC_JSK_POLL_MAX);
+
+ err = input_register_device(priv->dev);
+ if (err) {
+ dev_err(&client->dev, "failed to register joystick: %d\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_qwiic_match[] = {
+ { .compatible = "sparkfun,qwiic-joystick", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, of_qwiic_match);
+#endif /* CONFIG_OF */
+
+static const struct i2c_device_id qwiic_id_table[] = {
+ { KBUILD_MODNAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, qwiic_id_table);
+
+static struct i2c_driver qwiic_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(of_qwiic_match),
+ },
+ .id_table = qwiic_id_table,
+ .probe_new = qwiic_probe,
+};
+module_i2c_driver(qwiic_driver);
+
+MODULE_AUTHOR("Oleh Kravchenko <oleg@kaa.org.ua>");
+MODULE_DESCRIPTION("SparkFun Qwiic Joystick driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index edc613efc158..fbdef95291e9 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -324,7 +324,7 @@ static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf)
static umode_t atkbd_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct atkbd *atkbd = serio_get_drvdata(serio);
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 38457d9641bd..fc02c540636e 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -644,7 +644,7 @@ static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
struct attribute *attr,
int n)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
if (attr == &dev_attr_function_row_physmap.attr &&
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index bb29a7c9a1c0..54afb38601b9 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv)
HIL_IDD_NUM_AXES_PER_SET(*idd)) {
printk(KERN_INFO PREFIX
"combo devices are not supported.\n");
+ error = -EINVAL;
goto bail1;
}
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 81de8c4e37d0..6f38aa23a1ff 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -647,8 +647,8 @@ static int __ims_pcu_execute_command(struct ims_pcu *pcu,
#define IMS_PCU_BL_DATA_OFFSET 3
static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
- u8 command, const void *data, size_t len,
- u8 expected_response, int response_time)
+ u8 command, const void *data, size_t len,
+ u8 expected_response, int response_time)
{
int error;
@@ -1228,7 +1228,7 @@ static struct attribute *ims_pcu_attrs[] = {
static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct usb_interface *intf = to_usb_interface(dev);
struct ims_pcu *pcu = usb_get_intfdata(intf);
umode_t mode = attr->mode;
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c
index cf8104454e74..10e3fc0eac6e 100644
--- a/drivers/input/misc/pm8941-pwrkey.c
+++ b/drivers/input/misc/pm8941-pwrkey.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, 2020-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2014, Sony Mobile Communications Inc.
*/
@@ -22,6 +22,8 @@
#define PON_RT_STS 0x10
#define PON_KPDPWR_N_SET BIT(0)
#define PON_RESIN_N_SET BIT(1)
+#define PON_GEN3_RESIN_N_SET BIT(6)
+#define PON_GEN3_KPDPWR_N_SET BIT(7)
#define PON_PS_HOLD_RST_CTL 0x5a
#define PON_PS_HOLD_RST_CTL2 0x5b
@@ -38,8 +40,12 @@
#define PON_DBC_DELAY_MASK 0x7
struct pm8941_data {
- unsigned int pull_up_bit;
- unsigned int status_bit;
+ unsigned int pull_up_bit;
+ unsigned int status_bit;
+ bool supports_ps_hold_poff_config;
+ bool supports_debounce_config;
+ const char *name;
+ const char *phys;
};
struct pm8941_pwrkey {
@@ -231,34 +237,40 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
input_set_capability(pwrkey->input, EV_KEY, pwrkey->code);
- pwrkey->input->name = "pm8941_pwrkey";
- pwrkey->input->phys = "pm8941_pwrkey/input0";
-
- req_delay = (req_delay << 6) / USEC_PER_SEC;
- req_delay = ilog2(req_delay);
-
- error = regmap_update_bits(pwrkey->regmap,
- pwrkey->baseaddr + PON_DBC_CTL,
- PON_DBC_DELAY_MASK,
- req_delay);
- if (error) {
- dev_err(&pdev->dev, "failed to set debounce: %d\n", error);
- return error;
+ pwrkey->input->name = pwrkey->data->name;
+ pwrkey->input->phys = pwrkey->data->phys;
+
+ if (pwrkey->data->supports_debounce_config) {
+ req_delay = (req_delay << 6) / USEC_PER_SEC;
+ req_delay = ilog2(req_delay);
+
+ error = regmap_update_bits(pwrkey->regmap,
+ pwrkey->baseaddr + PON_DBC_CTL,
+ PON_DBC_DELAY_MASK,
+ req_delay);
+ if (error) {
+ dev_err(&pdev->dev, "failed to set debounce: %d\n",
+ error);
+ return error;
+ }
}
- error = regmap_update_bits(pwrkey->regmap,
- pwrkey->baseaddr + PON_PULL_CTL,
- pwrkey->data->pull_up_bit,
- pull_up ? pwrkey->data->pull_up_bit : 0);
- if (error) {
- dev_err(&pdev->dev, "failed to set pull: %d\n", error);
- return error;
+ if (pwrkey->data->pull_up_bit) {
+ error = regmap_update_bits(pwrkey->regmap,
+ pwrkey->baseaddr + PON_PULL_CTL,
+ pwrkey->data->pull_up_bit,
+ pull_up ? pwrkey->data->pull_up_bit :
+ 0);
+ if (error) {
+ dev_err(&pdev->dev, "failed to set pull: %d\n", error);
+ return error;
+ }
}
error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq,
NULL, pm8941_pwrkey_irq,
IRQF_ONESHOT,
- "pm8941_pwrkey", pwrkey);
+ pwrkey->data->name, pwrkey);
if (error) {
dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error);
return error;
@@ -271,12 +283,14 @@ static int pm8941_pwrkey_probe(struct platform_device *pdev)
return error;
}
- pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
- error = register_reboot_notifier(&pwrkey->reboot_notifier);
- if (error) {
- dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
- error);
- return error;
+ if (pwrkey->data->supports_ps_hold_poff_config) {
+ pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify,
+ error = register_reboot_notifier(&pwrkey->reboot_notifier);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register reboot notifier: %d\n",
+ error);
+ return error;
+ }
}
platform_set_drvdata(pdev, pwrkey);
@@ -289,7 +303,8 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
{
struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev);
- unregister_reboot_notifier(&pwrkey->reboot_notifier);
+ if (pwrkey->data->supports_ps_hold_poff_config)
+ unregister_reboot_notifier(&pwrkey->reboot_notifier);
return 0;
}
@@ -297,16 +312,42 @@ static int pm8941_pwrkey_remove(struct platform_device *pdev)
static const struct pm8941_data pwrkey_data = {
.pull_up_bit = PON_KPDPWR_PULL_UP,
.status_bit = PON_KPDPWR_N_SET,
+ .name = "pm8941_pwrkey",
+ .phys = "pm8941_pwrkey/input0",
+ .supports_ps_hold_poff_config = true,
+ .supports_debounce_config = true,
};
static const struct pm8941_data resin_data = {
.pull_up_bit = PON_RESIN_PULL_UP,
.status_bit = PON_RESIN_N_SET,
+ .name = "pm8941_resin",
+ .phys = "pm8941_resin/input0",
+ .supports_ps_hold_poff_config = true,
+ .supports_debounce_config = true,
+};
+
+static const struct pm8941_data pon_gen3_pwrkey_data = {
+ .status_bit = PON_GEN3_KPDPWR_N_SET,
+ .name = "pmic_pwrkey",
+ .phys = "pmic_pwrkey/input0",
+ .supports_ps_hold_poff_config = false,
+ .supports_debounce_config = false,
+};
+
+static const struct pm8941_data pon_gen3_resin_data = {
+ .status_bit = PON_GEN3_RESIN_N_SET,
+ .name = "pmic_resin",
+ .phys = "pmic_resin/input0",
+ .supports_ps_hold_poff_config = false,
+ .supports_debounce_config = false,
};
static const struct of_device_id pm8941_pwr_key_id_table[] = {
{ .compatible = "qcom,pm8941-pwrkey", .data = &pwrkey_data },
{ .compatible = "qcom,pm8941-resin", .data = &resin_data },
+ { .compatible = "qcom,pmk8350-pwrkey", .data = &pon_gen3_pwrkey_data },
+ { .compatible = "qcom,pmk8350-resin", .data = &pon_gen3_resin_data },
{ }
};
MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table);
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index ef2fa0905208..4a86b3e31d3b 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -214,7 +214,7 @@ static bool trackpoint_is_attr_available(struct psmouse *psmouse,
static umode_t trackpoint_is_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct serio *serio = to_serio_port(dev);
struct psmouse *psmouse = serio_get_drvdata(serio);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index abae23af0791..0b9f1d0a8f8b 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -139,7 +139,7 @@ static DEFINE_SPINLOCK(i8042_lock);
/*
* Writers to AUX and KBD ports as well as users issuing i8042_command
* directly should acquire i8042_mutex (by means of calling
- * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that
+ * i8042_lock_chip() and i8042_unlock_chip() helpers) to ensure that
* they do not disturb each other (unfortunately in many i8042
* implementations write to one of the ports will immediately abort
* command that is being processed by another port).
@@ -979,7 +979,7 @@ static int i8042_controller_selftest(void)
}
/*
- * i8042_controller init initializes the i8042 controller, and,
+ * i8042_controller_init initializes the i8042 controller, and,
* most importantly, sets it into non-xlated mode if that's
* desired.
*/
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index f465bae618fe..495ef156cf43 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -7,15 +7,14 @@
* Some cleanups by Alan Cox <alan@linux.intel.com>
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/i2c.h>
#include <linux/input.h>
-#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/input/cy8ctmg110_pdata.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
#define CY8CTMG110_DRIVER_NAME "cy8ctmg110"
@@ -45,18 +44,18 @@ struct cy8ctmg110 {
struct input_dev *input;
char phys[32];
struct i2c_client *client;
- int reset_pin;
- int irq_pin;
+ struct gpio_desc *reset_gpio;
};
/*
* cy8ctmg110_power is the routine that is called when touch hardware
- * will powered off or on.
+ * is being powered off or on. When powering on this routine de-asserts
+ * the RESET line, when powering off reset line is asserted.
*/
static void cy8ctmg110_power(struct cy8ctmg110 *ts, bool poweron)
{
- if (ts->reset_pin)
- gpio_direction_output(ts->reset_pin, 1 - poweron);
+ if (ts->reset_gpio)
+ gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
}
static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg,
@@ -112,7 +111,6 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
{
struct input_dev *input = tsc->input;
unsigned char reg_p[CY8CTMG110_REG_MAX];
- int x, y;
memset(reg_p, 0, CY8CTMG110_REG_MAX);
@@ -120,16 +118,15 @@ static int cy8ctmg110_touch_pos(struct cy8ctmg110 *tsc)
if (cy8ctmg110_read_regs(tsc, reg_p, 9, CY8CTMG110_TOUCH_X1) != 0)
return -EIO;
- y = reg_p[2] << 8 | reg_p[3];
- x = reg_p[0] << 8 | reg_p[1];
-
/* Number of touch */
if (reg_p[8] == 0) {
input_report_key(input, BTN_TOUCH, 0);
} else {
input_report_key(input, BTN_TOUCH, 1);
- input_report_abs(input, ABS_X, x);
- input_report_abs(input, ABS_Y, y);
+ input_report_abs(input, ABS_X,
+ be16_to_cpup((__be16 *)(reg_p + 0)));
+ input_report_abs(input, ABS_Y,
+ be16_to_cpup((__be16 *)(reg_p + 2)));
}
input_sync(input);
@@ -163,35 +160,35 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void cy8ctmg110_shut_off(void *_ts)
+{
+ struct cy8ctmg110 *ts = _ts;
+
+ cy8ctmg110_set_sleepmode(ts, true);
+ cy8ctmg110_power(ts, false);
+}
+
static int cy8ctmg110_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- const struct cy8ctmg110_pdata *pdata = dev_get_platdata(&client->dev);
struct cy8ctmg110 *ts;
struct input_dev *input_dev;
int err;
- /* No pdata no way forward */
- if (pdata == NULL) {
- dev_err(&client->dev, "no pdata\n");
- return -ENODEV;
- }
-
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_WORD_DATA))
return -EIO;
- ts = kzalloc(sizeof(struct cy8ctmg110), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!ts || !input_dev) {
- err = -ENOMEM;
- goto err_free_mem;
- }
+ ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ input_dev = devm_input_allocate_device(&client->dev);
+ if (!input_dev)
+ return -ENOMEM;
ts->client = client;
ts->input = input_dev;
- ts->reset_pin = pdata->reset_pin;
- ts->irq_pin = pdata->irq_pin;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
@@ -199,84 +196,46 @@ static int cy8ctmg110_probe(struct i2c_client *client,
input_dev->name = CY8CTMG110_DRIVER_NAME " Touchscreen";
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
- input_dev->dev.parent = &client->dev;
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X,
CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
input_set_abs_params(input_dev, ABS_Y,
CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
- if (ts->reset_pin) {
- err = gpio_request(ts->reset_pin, NULL);
- if (err) {
- dev_err(&client->dev,
- "Unable to request GPIO pin %d.\n",
- ts->reset_pin);
- goto err_free_mem;
- }
+ /* Request and assert reset line */
+ ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL,
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(ts->reset_gpio)) {
+ err = PTR_ERR(ts->reset_gpio);
+ dev_err(&client->dev,
+ "Unable to request reset GPIO: %d\n", err);
+ return err;
}
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
- err = gpio_request(ts->irq_pin, "touch_irq_key");
- if (err < 0) {
- dev_err(&client->dev,
- "Failed to request GPIO %d, error %d\n",
- ts->irq_pin, err);
- goto err_shutoff_device;
- }
-
- err = gpio_direction_input(ts->irq_pin);
- if (err < 0) {
- dev_err(&client->dev,
- "Failed to configure input direction for GPIO %d, error %d\n",
- ts->irq_pin, err);
- goto err_free_irq_gpio;
- }
-
- client->irq = gpio_to_irq(ts->irq_pin);
- if (client->irq < 0) {
- err = client->irq;
- dev_err(&client->dev,
- "Unable to get irq number for GPIO %d, error %d\n",
- ts->irq_pin, err);
- goto err_free_irq_gpio;
- }
+ err = devm_add_action_or_reset(&client->dev, cy8ctmg110_shut_off, ts);
+ if (err)
+ return err;
- err = request_threaded_irq(client->irq, NULL, cy8ctmg110_irq_thread,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- "touch_reset_key", ts);
- if (err < 0) {
+ err = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, cy8ctmg110_irq_thread,
+ IRQF_ONESHOT, "touch_reset_key", ts);
+ if (err) {
dev_err(&client->dev,
"irq %d busy? error %d\n", client->irq, err);
- goto err_free_irq_gpio;
+ return err;
}
err = input_register_device(input_dev);
if (err)
- goto err_free_irq;
+ return err;
i2c_set_clientdata(client, ts);
- device_init_wakeup(&client->dev, 1);
- return 0;
-err_free_irq:
- free_irq(client->irq, ts);
-err_free_irq_gpio:
- gpio_free(ts->irq_pin);
-err_shutoff_device:
- cy8ctmg110_set_sleepmode(ts, true);
- cy8ctmg110_power(ts, false);
- if (ts->reset_pin)
- gpio_free(ts->reset_pin);
-err_free_mem:
- input_free_device(input_dev);
- kfree(ts);
- return err;
+ return 0;
}
static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
@@ -284,12 +243,11 @@ static int __maybe_unused cy8ctmg110_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev))
- enable_irq_wake(client->irq);
- else {
+ if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_set_sleepmode(ts, true);
cy8ctmg110_power(ts, false);
}
+
return 0;
}
@@ -298,34 +256,16 @@ static int __maybe_unused cy8ctmg110_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct cy8ctmg110 *ts = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev))
- disable_irq_wake(client->irq);
- else {
+ if (!device_may_wakeup(&client->dev)) {
cy8ctmg110_power(ts, true);
cy8ctmg110_set_sleepmode(ts, false);
}
+
return 0;
}
static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume);
-static int cy8ctmg110_remove(struct i2c_client *client)
-{
- struct cy8ctmg110 *ts = i2c_get_clientdata(client);
-
- cy8ctmg110_set_sleepmode(ts, true);
- cy8ctmg110_power(ts, false);
-
- free_irq(client->irq, ts);
- input_unregister_device(ts->input);
- gpio_free(ts->irq_pin);
- if (ts->reset_pin)
- gpio_free(ts->reset_pin);
- kfree(ts);
-
- return 0;
-}
-
static const struct i2c_device_id cy8ctmg110_idtable[] = {
{ CY8CTMG110_DRIVER_NAME, 1 },
{ }
@@ -340,7 +280,6 @@ static struct i2c_driver cy8ctmg110_driver = {
},
.id_table = cy8ctmg110_idtable,
.probe = cy8ctmg110_probe,
- .remove = cy8ctmg110_remove,
};
module_i2c_driver(cy8ctmg110_driver);
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index 106dd4962785..1dbd849c9613 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/property.h>
#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
#include "cyttsp_core.h"
@@ -45,8 +46,15 @@
#define CY_MAXZ 255
#define CY_DELAY_DFLT 20 /* ms */
#define CY_DELAY_MAX 500
-#define CY_ACT_DIST_DFLT 0xF8
+/* Active distance in pixels for a gesture to be reported */
+#define CY_ACT_DIST_DFLT 0xF8 /* pixels */
#define CY_ACT_DIST_MASK 0x0F
+/* Active Power state scanning/processing refresh interval */
+#define CY_ACT_INTRVL_DFLT 0x00 /* ms */
+/* Low Power state scanning/processing refresh interval */
+#define CY_LP_INTRVL_DFLT 0x0A /* ms */
+/* touch timeout for the Active power */
+#define CY_TCH_TMOUT_DFLT 0xFF /* ms */
#define CY_HNDSHK_BIT 0x80
/* device mode bits */
#define CY_OPERATE_MODE 0x00
@@ -608,6 +616,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts)
return 0;
}
+static void cyttsp_disable_regulators(void *_ts)
+{
+ struct cyttsp *ts = _ts;
+
+ regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
+ ts->regulators);
+}
+
struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
struct device *dev, int irq, size_t xfer_buf_size)
{
@@ -628,6 +644,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
ts->bus_ops = bus_ops;
ts->irq = irq;
+ /*
+ * VCPIN is the analog voltage supply
+ * VDD is the digital voltage supply
+ */
+ ts->regulators[0].supply = "vcpin";
+ ts->regulators[1].supply = "vdd";
+ error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators),
+ ts->regulators);
+ if (error) {
+ dev_err(dev, "Failed to get regulators: %d\n", error);
+ return ERR_PTR(error);
+ }
+
+ error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
+ ts->regulators);
+ if (error) {
+ dev_err(dev, "Cannot enable regulators: %d\n", error);
+ return ERR_PTR(error);
+ }
+
+ error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts);
+ if (error) {
+ dev_err(dev, "failed to install chip disable handler\n");
+ return ERR_PTR(error);
+ }
+
ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ts->reset_gpio)) {
error = PTR_ERR(ts->reset_gpio);
@@ -664,8 +706,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
}
error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
- IRQF_NO_AUTOEN,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN,
"cyttsp", ts);
if (error) {
dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h
index 9bc4fe7e6ac5..075509e695a2 100644
--- a/drivers/input/touchscreen/cyttsp_core.h
+++ b/drivers/input/touchscreen/cyttsp_core.h
@@ -22,7 +22,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/device.h>
-#include <linux/input/cyttsp.h>
+#include <linux/regulator/consumer.h>
#define CY_NUM_RETRY 16 /* max number of retries for read ops */
@@ -122,6 +122,7 @@ struct cyttsp {
enum cyttsp_state state;
bool suspended;
+ struct regulator_bulk_data regulators[2];
struct gpio_desc *reset_gpio;
bool use_hndshk;
u8 act_dist;
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index 061debf64a2b..4c8473d327ab 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -18,6 +18,8 @@
#include <linux/i2c.h>
#include <linux/input.h>
+#define CY_I2C_NAME "cyttsp-i2c"
+
#define CY_I2C_DATA_SIZE 128
static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = {
@@ -52,10 +54,18 @@ static const struct i2c_device_id cyttsp_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
+static const struct of_device_id cyttsp_of_i2c_match[] = {
+ { .compatible = "cypress,cy8ctma340", },
+ { .compatible = "cypress,cy8ctst341", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cyttsp_of_i2c_match);
+
static struct i2c_driver cyttsp_i2c_driver = {
.driver = {
.name = CY_I2C_NAME,
.pm = &cyttsp_pm_ops,
+ .of_match_table = cyttsp_of_i2c_match,
},
.probe = cyttsp_i2c_probe,
.id_table = cyttsp_i2c_id,
diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c
index 54e410921d53..30c6fbf86a86 100644
--- a/drivers/input/touchscreen/cyttsp_spi.c
+++ b/drivers/input/touchscreen/cyttsp_spi.c
@@ -20,6 +20,8 @@
#include <linux/input.h>
#include <linux/spi/spi.h>
+#define CY_SPI_NAME "cyttsp-spi"
+
#define CY_SPI_WR_OP 0x00 /* r/~w */
#define CY_SPI_RD_OP 0x01
#define CY_SPI_CMD_BYTES 4
@@ -160,10 +162,18 @@ static int cyttsp_spi_probe(struct spi_device *spi)
return 0;
}
+static const struct of_device_id cyttsp_of_spi_match[] = {
+ { .compatible = "cypress,cy8ctma340", },
+ { .compatible = "cypress,cy8ctst341", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cyttsp_of_spi_match);
+
static struct spi_driver cyttsp_spi_driver = {
.driver = {
.name = CY_SPI_NAME,
.pm = &cyttsp_pm_ops,
+ .of_match_table = cyttsp_of_spi_match,
},
.probe = cyttsp_spi_probe,
};
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 2eefbc2485bc..263de3bfb6cd 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -104,6 +104,7 @@ struct edt_ft5x06_ts_data {
u16 num_x;
u16 num_y;
struct regulator *vcc;
+ struct regulator *iovcc;
struct gpio_desc *reset_gpio;
struct gpio_desc *wake_gpio;
@@ -1062,11 +1063,12 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
-static void edt_ft5x06_disable_regulator(void *arg)
+static void edt_ft5x06_disable_regulators(void *arg)
{
struct edt_ft5x06_ts_data *data = arg;
regulator_disable(data->vcc);
+ regulator_disable(data->iovcc);
}
static int edt_ft5x06_ts_probe(struct i2c_client *client,
@@ -1107,14 +1109,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
return error;
}
+ tsdata->iovcc = devm_regulator_get(&client->dev, "iovcc");
+ if (IS_ERR(tsdata->iovcc)) {
+ error = PTR_ERR(tsdata->iovcc);
+ if (error != -EPROBE_DEFER)
+ dev_err(&client->dev,
+ "failed to request iovcc regulator: %d\n", error);
+ return error;
+ }
+
+ error = regulator_enable(tsdata->iovcc);
+ if (error < 0) {
+ dev_err(&client->dev, "failed to enable iovcc: %d\n", error);
+ return error;
+ }
+
+ /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
+ usleep_range(10, 100);
+
error = regulator_enable(tsdata->vcc);
if (error < 0) {
dev_err(&client->dev, "failed to enable vcc: %d\n", error);
+ regulator_disable(tsdata->iovcc);
return error;
}
error = devm_add_action_or_reset(&client->dev,
- edt_ft5x06_disable_regulator,
+ edt_ft5x06_disable_regulators,
tsdata);
if (error)
return error;
@@ -1289,6 +1310,9 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
ret = regulator_disable(tsdata->vcc);
if (ret)
dev_warn(dev, "Failed to disable vcc\n");
+ ret = regulator_disable(tsdata->iovcc);
+ if (ret)
+ dev_warn(dev, "Failed to disable iovcc\n");
return 0;
}
@@ -1319,9 +1343,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
gpiod_set_value_cansleep(reset_gpio, 1);
usleep_range(5000, 6000);
+ ret = regulator_enable(tsdata->iovcc);
+ if (ret) {
+ dev_err(dev, "Failed to enable iovcc\n");
+ return ret;
+ }
+
+ /* Delay enabling VCC for > 10us (T_ivd) after IOVCC */
+ usleep_range(10, 100);
+
ret = regulator_enable(tsdata->vcc);
if (ret) {
dev_err(dev, "Failed to enable vcc\n");
+ regulator_disable(tsdata->iovcc);
return ret;
}
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index ddad4a82a5e5..e9547ee29756 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts)
return -EIO;
}
-static void hideep_nvm_unlock(struct hideep_ts *ts)
+static int hideep_nvm_unlock(struct hideep_ts *ts)
{
u32 unmask_code;
+ int error;
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
- hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
+ error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
+ if (error)
+ return error;
/* make it unprotected code */
unmask_code &= ~HIDEEP_PROT_MODE;
@@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts)
NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
SET_FLASH_HWCONTROL();
hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
+
+ return 0;
}
static int hideep_check_status(struct hideep_ts *ts)
@@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts,
u32 addr = 0;
int error;
- hideep_nvm_unlock(ts);
+ error = hideep_nvm_unlock(ts);
+ if (error)
+ return error;
while (ucode_len > 0) {
xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c
index e50af30183f4..744544a723b7 100644
--- a/drivers/input/touchscreen/resistive-adc-touch.c
+++ b/drivers/input/touchscreen/resistive-adc-touch.c
@@ -13,44 +13,78 @@
#include <linux/input/touchscreen.h>
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#define DRIVER_NAME "resistive-adc-touch"
#define GRTS_DEFAULT_PRESSURE_MIN 50000
+#define GRTS_DEFAULT_PRESSURE_MAX 65535
#define GRTS_MAX_POS_MASK GENMASK(11, 0)
+#define GRTS_MAX_CHANNELS 4
+
+enum grts_ch_type {
+ GRTS_CH_X,
+ GRTS_CH_Y,
+ GRTS_CH_PRESSURE,
+ GRTS_CH_Z1,
+ GRTS_CH_Z2,
+ GRTS_CH_MAX = GRTS_CH_Z2 + 1
+};
/**
* struct grts_state - generic resistive touch screen information struct
+ * @x_plate_ohms: resistance of the X plate
* @pressure_min: number representing the minimum for the pressure
* @pressure: are we getting pressure info or not
* @iio_chans: list of channels acquired
* @iio_cb: iio_callback buffer for the data
* @input: the input device structure that we register
* @prop: touchscreen properties struct
+ * @ch_map: map of channels that are defined for the touchscreen
*/
struct grts_state {
+ u32 x_plate_ohms;
u32 pressure_min;
bool pressure;
struct iio_channel *iio_chans;
struct iio_cb_buffer *iio_cb;
struct input_dev *input;
struct touchscreen_properties prop;
+ u8 ch_map[GRTS_CH_MAX];
};
static int grts_cb(const void *data, void *private)
{
const u16 *touch_info = data;
struct grts_state *st = private;
- unsigned int x, y, press = 0x0;
-
- /* channel data coming in buffer in the order below */
- x = touch_info[0];
- y = touch_info[1];
- if (st->pressure)
- press = touch_info[2];
+ unsigned int x, y, press = 0;
+
+ x = touch_info[st->ch_map[GRTS_CH_X]];
+ y = touch_info[st->ch_map[GRTS_CH_Y]];
+
+ if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
+ press = touch_info[st->ch_map[GRTS_CH_PRESSURE]];
+ } else if (st->ch_map[GRTS_CH_Z1] < GRTS_MAX_CHANNELS) {
+ unsigned int z1 = touch_info[st->ch_map[GRTS_CH_Z1]];
+ unsigned int z2 = touch_info[st->ch_map[GRTS_CH_Z2]];
+ unsigned int Rt;
+
+ Rt = z2;
+ Rt -= z1;
+ Rt *= st->x_plate_ohms;
+ Rt = DIV_ROUND_CLOSEST(Rt, 16);
+ Rt *= x;
+ Rt /= z1;
+ Rt = DIV_ROUND_CLOSEST(Rt, 256);
+ /*
+ * On increased pressure the resistance (Rt) is decreasing
+ * so, convert values to make it looks as real pressure.
+ */
+ if (Rt < GRTS_DEFAULT_PRESSURE_MAX)
+ press = GRTS_DEFAULT_PRESSURE_MAX - Rt;
+ }
if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
/* report end of touch */
@@ -94,12 +128,77 @@ static void grts_disable(void *data)
iio_channel_release_all_cb(data);
}
+static int grts_map_channel(struct grts_state *st, struct device *dev,
+ enum grts_ch_type type, const char *name,
+ bool optional)
+{
+ int idx;
+
+ idx = device_property_match_string(dev, "io-channel-names", name);
+ if (idx < 0) {
+ if (!optional)
+ return idx;
+ idx = GRTS_MAX_CHANNELS;
+ } else if (idx >= GRTS_MAX_CHANNELS) {
+ return -EOVERFLOW;
+ }
+
+ st->ch_map[type] = idx;
+ return 0;
+}
+
+static int grts_get_properties(struct grts_state *st, struct device *dev)
+{
+ int error;
+
+ error = grts_map_channel(st, dev, GRTS_CH_X, "x", false);
+ if (error)
+ return error;
+
+ error = grts_map_channel(st, dev, GRTS_CH_Y, "y", false);
+ if (error)
+ return error;
+
+ /* pressure is optional */
+ error = grts_map_channel(st, dev, GRTS_CH_PRESSURE, "pressure", true);
+ if (error)
+ return error;
+
+ if (st->ch_map[GRTS_CH_PRESSURE] < GRTS_MAX_CHANNELS) {
+ st->pressure = true;
+ return 0;
+ }
+
+ /* if no pressure is defined, try optional z1 + z2 */
+ error = grts_map_channel(st, dev, GRTS_CH_Z1, "z1", true);
+ if (error)
+ return error;
+
+ if (st->ch_map[GRTS_CH_Z1] >= GRTS_MAX_CHANNELS)
+ return 0;
+
+ /* if z1 is provided z2 is not optional */
+ error = grts_map_channel(st, dev, GRTS_CH_Z2, "z2", true);
+ if (error)
+ return error;
+
+ error = device_property_read_u32(dev,
+ "touchscreen-x-plate-ohms",
+ &st->x_plate_ohms);
+ if (error) {
+ dev_err(dev, "can't get touchscreen-x-plate-ohms property\n");
+ return error;
+ }
+
+ st->pressure = true;
+ return 0;
+}
+
static int grts_probe(struct platform_device *pdev)
{
struct grts_state *st;
struct input_dev *input;
struct device *dev = &pdev->dev;
- struct iio_channel *chan;
int error;
st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
@@ -115,12 +214,13 @@ static int grts_probe(struct platform_device *pdev)
return error;
}
- chan = &st->iio_chans[0];
- st->pressure = false;
- while (chan && chan->indio_dev) {
- if (!strcmp(chan->channel->datasheet_name, "pressure"))
- st->pressure = true;
- chan++;
+ if (!device_property_present(dev, "io-channel-names"))
+ return -ENODEV;
+
+ error = grts_get_properties(st, dev);
+ if (error) {
+ dev_err(dev, "Failed to parse properties\n");
+ return error;
}
if (st->pressure) {
@@ -148,7 +248,7 @@ static int grts_probe(struct platform_device *pdev)
input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
if (st->pressure)
input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
- 0xffff, 0, 0);
+ GRTS_DEFAULT_PRESSURE_MAX, 0, 0);
input_set_capability(input, EV_KEY, BTN_TOUCH);
@@ -193,7 +293,7 @@ static struct platform_driver grts_driver = {
.probe = grts_probe,
.driver = {
.name = DRIVER_NAME,
- .of_match_table = of_match_ptr(grts_of_match),
+ .of_match_table = grts_of_match,
},
};
diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c
index ce2fe30d6b8a..b8d720d52013 100644
--- a/drivers/input/touchscreen/tsc200x-core.c
+++ b/drivers/input/touchscreen/tsc200x-core.c
@@ -338,7 +338,7 @@ static struct attribute *tsc200x_attrs[] = {
static umode_t tsc200x_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
- struct device *dev = container_of(kobj, struct device, kobj);
+ struct device *dev = kobj_to_dev(kobj);
struct tsc200x *ts = dev_get_drvdata(dev);
umode_t mode = attr->mode;