summaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2021-02-22 21:21:03 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2021-02-22 21:21:03 -0800
commit415e915fdfc775ad0c6675fde1008f6f43dd6251 (patch)
tree429851187c0e85daa78f5d2bb6853959a1f5545b /drivers/input
parente64123949e6c9581c97fc14594f1cf34bf1d87a8 (diff)
parentf40ddce88593482919761f74910f42f4b84c004b (diff)
downloadlinux-stable-415e915fdfc775ad0c6675fde1008f6f43dd6251.tar.gz
linux-stable-415e915fdfc775ad0c6675fde1008f6f43dd6251.tar.bz2
linux-stable-415e915fdfc775ad0c6675fde1008f6f43dd6251.zip
Merge tag 'v5.11' into next
Merge with mainline to get latest APIs and device tree bindings.
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/joystick/xpad.c19
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c3
-rw-r--r--drivers/input/keyboard/sunkbd.c41
-rw-r--r--drivers/input/misc/adxl34x.c2
-rw-r--r--drivers/input/misc/ariel-pwrbutton.c6
-rw-r--r--drivers/input/misc/cm109.c7
-rw-r--r--drivers/input/misc/soc_button_array.c12
-rw-r--r--drivers/input/mouse/elan_i2c.h2
-rw-r--r--drivers/input/mouse/elan_i2c_core.c3
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c10
-rw-r--r--drivers/input/mouse/elan_i2c_smbus.c2
-rw-r--r--drivers/input/serio/hil_mlc.c21
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c8
-rw-r--r--drivers/input/serio/hyperv-keyboard.c4
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h48
-rw-r--r--drivers/input/serio/i8042.c15
-rw-r--r--drivers/input/touchscreen/Kconfig1
-rw-r--r--drivers/input/touchscreen/ads7846.c3
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c4
-rw-r--r--drivers/input/touchscreen/goodix.c14
-rw-r--r--drivers/input/touchscreen/ili210x.c26
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c126
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c37
-rw-r--r--drivers/input/touchscreen/st1232.c48
24 files changed, 368 insertions, 94 deletions
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index e64c76c34fc1..8cc8ca4a9ac0 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -215,9 +215,17 @@ static const struct xpad_device {
{ 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE },
- { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a0, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a1, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a2, "PDP Wired Controller for Xbox One - Crimson Red", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x02a6, "PDP Wired Controller for Xbox One - Camo Series", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a7, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a8, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02ad, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02b3, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02b8, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
@@ -241,6 +249,7 @@ static const struct xpad_device {
{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
+ { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
{ 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -295,6 +304,9 @@ static const struct xpad_device {
{ 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
+ { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
+ { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
+ { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
{ 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
@@ -418,6 +430,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
+ XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
@@ -427,8 +440,12 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */
XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */
+ XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */
+ XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */
XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */
XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */
+ XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */
+ XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */
{ }
};
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 023f083dadd3..b379ed762878 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -184,6 +184,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
"changed: [r%d c%d]: byte %02x\n",
row, col, new_state);
+ input_event(idev, EV_MSC, MSC_SCAN, pos);
input_report_key(idev, keycodes[pos],
new_state);
}
@@ -349,7 +350,7 @@ static int cros_ec_keyb_info(struct cros_ec_device *ec_dev,
params->event_type = event_type;
ret = cros_ec_cmd_xfer_status(ec_dev, msg);
- if (ret == -ENOTSUPP) {
+ if (ret == -ENOPROTOOPT) {
/* With older ECs we just return 0 for everything */
memset(result, 0, result_size);
ret = 0;
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index 27126e621eb6..d450f11b98a7 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -99,7 +99,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio,
switch (data) {
case SUNKBD_RET_RESET:
- schedule_work(&sunkbd->tq);
+ if (sunkbd->enabled)
+ schedule_work(&sunkbd->tq);
sunkbd->reset = -1;
break;
@@ -200,16 +201,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd)
}
/*
- * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
- * were in.
+ * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
+ * they were in.
*/
-static void sunkbd_reinit(struct work_struct *work)
+static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
{
- struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
-
- wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
-
serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
serio_write(sunkbd->serio,
(!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) |
@@ -222,11 +219,39 @@ static void sunkbd_reinit(struct work_struct *work)
SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
}
+
+/*
+ * sunkbd_reinit() wait for the keyboard reset to complete and restores state
+ * of leds and beeps.
+ */
+
+static void sunkbd_reinit(struct work_struct *work)
+{
+ struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
+
+ /*
+ * It is OK that we check sunkbd->enabled without pausing serio,
+ * as we only want to catch true->false transition that will
+ * happen once and we will be woken up for it.
+ */
+ wait_event_interruptible_timeout(sunkbd->wait,
+ sunkbd->reset >= 0 || !sunkbd->enabled,
+ HZ);
+
+ if (sunkbd->reset >= 0 && sunkbd->enabled)
+ sunkbd_set_leds_beeps(sunkbd);
+}
+
static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
{
serio_pause_rx(sunkbd->serio);
sunkbd->enabled = enable;
serio_continue_rx(sunkbd->serio);
+
+ if (!enable) {
+ wake_up_interruptible(&sunkbd->wait);
+ cancel_work_sync(&sunkbd->tq);
+ }
}
/*
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c
index 5fe92d4ba3f0..4cc4e8ff42b3 100644
--- a/drivers/input/misc/adxl34x.c
+++ b/drivers/input/misc/adxl34x.c
@@ -696,7 +696,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq,
struct input_dev *input_dev;
const struct adxl34x_platform_data *pdata;
int err, range, i;
- unsigned char revid;
+ int revid;
if (!irq) {
dev_err(dev, "no IRQ?\n");
diff --git a/drivers/input/misc/ariel-pwrbutton.c b/drivers/input/misc/ariel-pwrbutton.c
index eda86ab552b9..17bbaac8b80c 100644
--- a/drivers/input/misc/ariel-pwrbutton.c
+++ b/drivers/input/misc/ariel-pwrbutton.c
@@ -149,12 +149,6 @@ static const struct of_device_id ariel_pwrbutton_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ariel_pwrbutton_of_match);
-static const struct spi_device_id ariel_pwrbutton_id_table[] = {
- { "wyse-ariel-ec-input", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(spi, ariel_pwrbutton_id_table);
-
static struct spi_driver ariel_pwrbutton_driver = {
.driver = {
.name = "dell-wyse-ariel-ec-input",
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index e413801f0491..f515fae465c3 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -568,12 +568,15 @@ static int cm109_input_open(struct input_dev *idev)
dev->ctl_data->byte[HID_OR2] = dev->keybit;
dev->ctl_data->byte[HID_OR3] = 0x00;
+ dev->ctl_urb_pending = 1;
error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
- if (error)
+ if (error) {
+ dev->ctl_urb_pending = 0;
dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
__func__, error);
- else
+ } else {
dev->open = 1;
+ }
mutex_unlock(&dev->pm_mutex);
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index cae1a3fae83a..cb6ec59a045d 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
@@ -82,6 +83,17 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "One S1003"),
},
},
+ {
+ /*
+ * Lenovo Yoga Tab2 1051L, something messes with the home-button
+ * IRQ settings, leading to a non working home-button.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "60073"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "1051L"),
+ },
+ },
{} /* Terminating entry */
};
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 84bb386e97fe..e12da5b024b0 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -94,7 +94,7 @@ struct elan_transport_ops {
int (*iap_reset)(struct i2c_client *client);
int (*prepare_fw_update)(struct i2c_client *client, u16 ic_type,
- u8 iap_version);
+ u8 iap_version, u16 fw_page_size);
int (*write_fw_block)(struct i2c_client *client, u16 fw_page_size,
const u8 *page, u16 checksum, int idx);
int (*finish_fw_update)(struct i2c_client *client,
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 3a8b9e890010..bef73822315d 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -484,7 +484,8 @@ static int __elan_update_firmware(struct elan_tp_data *data,
u16 sw_checksum = 0, fw_checksum = 0;
error = data->ops->prepare_fw_update(client, data->ic_type,
- data->iap_version);
+ data->iap_version,
+ data->fw_page_size);
if (error)
return error;
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index 5a496d4ffa49..13dc097eb6c6 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -517,7 +517,7 @@ static int elan_i2c_set_flash_key(struct i2c_client *client)
return 0;
}
-static int elan_read_write_iap_type(struct i2c_client *client)
+static int elan_read_write_iap_type(struct i2c_client *client, u16 fw_page_size)
{
int error;
u16 constant;
@@ -526,7 +526,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
do {
error = elan_i2c_write_cmd(client, ETP_I2C_IAP_TYPE_CMD,
- ETP_I2C_IAP_TYPE_REG);
+ fw_page_size / 2);
if (error) {
dev_err(&client->dev,
"cannot write iap type: %d\n", error);
@@ -543,7 +543,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
constant = le16_to_cpup((__le16 *)val);
dev_dbg(&client->dev, "iap type reg: 0x%04x\n", constant);
- if (constant == ETP_I2C_IAP_TYPE_REG)
+ if (constant == fw_page_size / 2)
return 0;
} while (--retry > 0);
@@ -553,7 +553,7 @@ static int elan_read_write_iap_type(struct i2c_client *client)
}
static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
- u8 iap_version)
+ u8 iap_version, u16 fw_page_size)
{
struct device *dev = &client->dev;
int error;
@@ -594,7 +594,7 @@ static int elan_i2c_prepare_fw_update(struct i2c_client *client, u16 ic_type,
}
if (ic_type >= 0x0D && iap_version >= 1) {
- error = elan_read_write_iap_type(client);
+ error = elan_read_write_iap_type(client, fw_page_size);
if (error)
return error;
}
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index 1f38fab1825a..6dc148b9d959 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -341,7 +341,7 @@ static int elan_smbus_set_flash_key(struct i2c_client *client)
}
static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type,
- u8 iap_version)
+ u8 iap_version, u16 fw_page_size)
{
struct device *dev = &client->dev;
int len;
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65f4e9d62a67..d36e89d6fc54 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(hil_mlc_unregister);
static LIST_HEAD(hil_mlcs);
static DEFINE_RWLOCK(hil_mlcs_lock);
static struct timer_list hil_mlcs_kicker;
-static int hil_mlcs_probe;
+static int hil_mlcs_probe, hil_mlc_stop;
static void hil_mlcs_process(unsigned long unused);
static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
@@ -702,9 +702,13 @@ static int hilse_donode(hil_mlc *mlc)
if (!mlc->ostarted) {
mlc->ostarted = 1;
mlc->opacket = pack;
- mlc->out(mlc);
+ rc = mlc->out(mlc);
nextidx = HILSEN_DOZE;
write_unlock_irqrestore(&mlc->lock, flags);
+ if (rc) {
+ hil_mlc_stop = 1;
+ return 1;
+ }
break;
}
mlc->ostarted = 0;
@@ -715,8 +719,13 @@ static int hilse_donode(hil_mlc *mlc)
case HILSE_CTS:
write_lock_irqsave(&mlc->lock, flags);
- nextidx = mlc->cts(mlc) ? node->bad : node->good;
+ rc = mlc->cts(mlc);
+ nextidx = rc ? node->bad : node->good;
write_unlock_irqrestore(&mlc->lock, flags);
+ if (rc) {
+ hil_mlc_stop = 1;
+ return 1;
+ }
break;
default:
@@ -780,6 +789,12 @@ static void hil_mlcs_process(unsigned long unused)
static void hil_mlcs_timer(struct timer_list *unused)
{
+ if (hil_mlc_stop) {
+ /* could not send packet - stop immediately. */
+ pr_warn(PREFIX "HIL seems stuck - Disabling HIL MLC.\n");
+ return;
+ }
+
hil_mlcs_probe = 1;
tasklet_schedule(&hil_mlcs_tasklet);
/* Re-insert the periodic task. */
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index 232d30c825bd..3e85e9039374 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -210,7 +210,7 @@ static int hp_sdc_mlc_cts(hil_mlc *mlc)
priv->tseq[2] = 1;
priv->tseq[3] = 0;
priv->tseq[4] = 0;
- __hp_sdc_enqueue_transaction(&priv->trans);
+ return __hp_sdc_enqueue_transaction(&priv->trans);
busy:
return 1;
done:
@@ -219,7 +219,7 @@ static int hp_sdc_mlc_cts(hil_mlc *mlc)
return 0;
}
-static void hp_sdc_mlc_out(hil_mlc *mlc)
+static int hp_sdc_mlc_out(hil_mlc *mlc)
{
struct hp_sdc_mlc_priv_s *priv;
@@ -234,7 +234,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
do_data:
if (priv->emtestmode) {
up(&mlc->osem);
- return;
+ return 0;
}
/* Shouldn't be sending commands when loop may be busy */
BUG_ON(down_trylock(&mlc->csem));
@@ -296,7 +296,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
BUG_ON(down_trylock(&mlc->csem));
}
enqueue:
- hp_sdc_enqueue_transaction(&priv->trans);
+ return hp_sdc_enqueue_transaction(&priv->trans);
}
static int __init hp_sdc_mlc_init(void)
diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c
index df4e9f6f4529..1a7b72a9016d 100644
--- a/drivers/input/serio/hyperv-keyboard.c
+++ b/drivers/input/serio/hyperv-keyboard.c
@@ -75,8 +75,8 @@ struct synth_kbd_keystroke {
#define HK_MAXIMUM_MESSAGE_SIZE 256
-#define KBD_VSC_SEND_RING_BUFFER_SIZE (40 * 1024)
-#define KBD_VSC_RECV_RING_BUFFER_SIZE (40 * 1024)
+#define KBD_VSC_SEND_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024)
+#define KBD_VSC_RECV_RING_BUFFER_SIZE VMBUS_RING_SIZE(36 * 1024)
#define XTKBD_EMUL0 0xe0
#define XTKBD_EMUL1 0xe1
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index d3fb1bc66f43..9119e12a5778 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -220,6 +220,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
},
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
+ },
+ },
{ }
};
@@ -612,6 +618,48 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
},
},
{
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),
+ },
+ },
+ {
/* Advent 4211 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index d3eda48032e3..abae23af0791 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -122,6 +122,7 @@ module_param_named(unmask_kbd_data, i8042_unmask_kbd_data, bool, 0600);
MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]");
#endif
+static bool i8042_present;
static bool i8042_bypass_aux_irq_test;
static char i8042_kbd_firmware_id[128];
static char i8042_aux_firmware_id[128];
@@ -343,6 +344,9 @@ int i8042_command(unsigned char *param, int command)
unsigned long flags;
int retval;
+ if (!i8042_present)
+ return -1;
+
spin_lock_irqsave(&i8042_lock, flags);
retval = __i8042_command(param, command);
spin_unlock_irqrestore(&i8042_lock, flags);
@@ -1467,7 +1471,8 @@ static int __init i8042_setup_aux(void)
if (error)
goto err_free_ports;
- if (aux_enable())
+ error = aux_enable();
+ if (error)
goto err_free_irq;
i8042_aux_irq_registered = true;
@@ -1612,12 +1617,15 @@ static int __init i8042_init(void)
err = i8042_platform_init();
if (err)
- return err;
+ return (err == -ENODEV) ? 0 : err;
err = i8042_controller_check();
if (err)
goto err_platform_exit;
+ /* Set this before creating the dev to allow i8042_command to work right away */
+ i8042_present = true;
+
pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0);
if (IS_ERR(pdev)) {
err = PTR_ERR(pdev);
@@ -1636,6 +1644,9 @@ static int __init i8042_init(void)
static void __exit i8042_exit(void)
{
+ if (!i8042_present)
+ return;
+
platform_device_unregister(i8042_platform_device);
platform_driver_unregister(&i8042_driver);
i8042_platform_exit();
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index d1b6ef9fd8d4..529614d364fe 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -96,6 +96,7 @@ config TOUCHSCREEN_AD7879_SPI
config TOUCHSCREEN_ADC
tristate "Generic ADC based resistive touchscreen"
depends on IIO
+ select IIO_BUFFER
select IIO_BUFFER_CB
help
Say Y here if you want to use the generic ADC
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 93fc182f5e84..f113a27aeb1e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1239,7 +1239,8 @@ static int ads7846_probe(struct spi_device *spi)
* may not. So we stick to very-portable 8 bit words, both RX and TX.
*/
spi->bits_per_word = 8;
- spi->mode = SPI_MODE_0;
+ spi->mode &= ~SPI_MODE_X_MASK;
+ spi->mode |= SPI_MODE_0;
err = spi_setup(spi);
if (err < 0)
return err;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f5a86aa9690e..383a848eb601 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2180,11 +2180,11 @@ static int mxt_initialize(struct mxt_data *data)
msleep(MXT_FW_RESET_TIME);
}
- error = mxt_acquire_irq(data);
+ error = mxt_check_retrigen(data);
if (error)
return error;
- error = mxt_check_retrigen(data);
+ error = mxt_acquire_irq(data);
if (error)
return error;
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index c1b728e47827..c682b028f0a2 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -157,6 +157,7 @@ static const struct goodix_chip_id goodix_chip_ids[] = {
{ .id = "5663", .data = &gt1x_chip_data },
{ .id = "5688", .data = &gt1x_chip_data },
{ .id = "917S", .data = &gt1x_chip_data },
+ { .id = "9286", .data = &gt1x_chip_data },
{ .id = "911", .data = &gt911_chip_data },
{ .id = "9271", .data = &gt911_chip_data },
@@ -193,6 +194,18 @@ static const struct dmi_system_id rotated_screen[] = {
},
},
{
+ .ident = "Teclast X98 Pro",
+ .matches = {
+ /*
+ * Only match BIOS date, because the manufacturers
+ * BIOS does not report the board name at all
+ * (sometimes)...
+ */
+ DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
+ DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"),
+ },
+ },
+ {
.ident = "WinBook TW100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
@@ -1436,6 +1449,7 @@ static const struct of_device_id goodix_of_match[] = {
{ .compatible = "goodix,gt927" },
{ .compatible = "goodix,gt9271" },
{ .compatible = "goodix,gt928" },
+ { .compatible = "goodix,gt9286" },
{ .compatible = "goodix,gt967" },
{ }
};
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 199cf3daec10..d8fccf048bf4 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -29,11 +29,13 @@ struct ili2xxx_chip {
void *buf, size_t len);
int (*get_touch_data)(struct i2c_client *client, u8 *data);
bool (*parse_touch_data)(const u8 *data, unsigned int finger,
- unsigned int *x, unsigned int *y);
+ unsigned int *x, unsigned int *y,
+ unsigned int *z);
bool (*continue_polling)(const u8 *data, bool touch);
unsigned int max_touches;
unsigned int resolution;
bool has_calibrate_reg;
+ bool has_pressure_reg;
};
struct ili210x {
@@ -82,7 +84,8 @@ static int ili210x_read_touch_data(struct i2c_client *client, u8 *data)
static bool ili210x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
- unsigned int *x, unsigned int *y)
+ unsigned int *x, unsigned int *y,
+ unsigned int *z)
{
if (touchdata[0] & BIT(finger))
return false;
@@ -137,7 +140,8 @@ static int ili211x_read_touch_data(struct i2c_client *client, u8 *data)
static bool ili211x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
- unsigned int *x, unsigned int *y)
+ unsigned int *x, unsigned int *y,
+ unsigned int *z)
{
u32 data;
@@ -169,7 +173,8 @@ static const struct ili2xxx_chip ili211x_chip = {
static bool ili212x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
- unsigned int *x, unsigned int *y)
+ unsigned int *x, unsigned int *y,
+ unsigned int *z)
{
u16 val;
@@ -235,7 +240,8 @@ static int ili251x_read_touch_data(struct i2c_client *client, u8 *data)
static bool ili251x_touchdata_to_coords(const u8 *touchdata,
unsigned int finger,
- unsigned int *x, unsigned int *y)
+ unsigned int *x, unsigned int *y,
+ unsigned int *z)
{
u16 val;
@@ -245,6 +251,7 @@ static bool ili251x_touchdata_to_coords(const u8 *touchdata,
*x = val & 0x3fff;
*y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
+ *z = touchdata[1 + (finger * 5) + 4];
return true;
}
@@ -261,6 +268,7 @@ static const struct ili2xxx_chip ili251x_chip = {
.continue_polling = ili251x_check_continue_polling,
.max_touches = 10,
.has_calibrate_reg = true,
+ .has_pressure_reg = true,
};
static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
@@ -268,14 +276,16 @@ static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
struct input_dev *input = priv->input;
int i;
bool contact = false, touch;
- unsigned int x = 0, y = 0;
+ unsigned int x = 0, y = 0, z = 0;
for (i = 0; i < priv->chip->max_touches; i++) {
- touch = priv->chip->parse_touch_data(touchdata, i, &x, &y);
+ touch = priv->chip->parse_touch_data(touchdata, i, &x, &y, &z);
input_mt_slot(input, i);
if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) {
touchscreen_report_pos(input, &priv->prop, x, y, true);
+ if (priv->chip->has_pressure_reg)
+ input_report_abs(input, ABS_MT_PRESSURE, z);
contact = true;
}
}
@@ -437,6 +447,8 @@ static int ili210x_i2c_probe(struct i2c_client *client,
max_xy = (chip->resolution ?: SZ_64K) - 1;
input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0);
+ if (priv->chip->has_pressure_reg)
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0);
touchscreen_parse_properties(input, true, &priv->prop);
error = input_mt_init_slots(input, priv->chip->max_touches,
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index 678afac85507..4d2d22a86977 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -137,45 +137,25 @@ struct raydium_data {
bool wake_irq_enabled;
};
-static int raydium_i2c_xfer(struct i2c_client *client,
- u32 addr, void *data, size_t len, bool is_read)
-{
- struct raydium_bank_switch_header {
- u8 cmd;
- __be32 be_addr;
- } __packed header = {
- .cmd = RM_CMD_BANK_SWITCH,
- .be_addr = cpu_to_be32(addr),
- };
-
- u8 reg_addr = addr & 0xff;
-
- struct i2c_msg xfer[] = {
- {
- .addr = client->addr,
- .len = sizeof(header),
- .buf = (u8 *)&header,
- },
- {
- .addr = client->addr,
- .len = 1,
- .buf = &reg_addr,
- },
- {
- .addr = client->addr,
- .len = len,
- .buf = data,
- .flags = is_read ? I2C_M_RD : 0,
- }
- };
+/*
+ * Header to be sent for RM_CMD_BANK_SWITCH command. This is used by
+ * raydium_i2c_{read|send} below.
+ */
+struct __packed raydium_bank_switch_header {
+ u8 cmd;
+ __be32 be_addr;
+};
+static int raydium_i2c_xfer(struct i2c_client *client, u32 addr,
+ struct i2c_msg *xfer, size_t xfer_count)
+{
+ int ret;
/*
* If address is greater than 255, then RM_CMD_BANK_SWITCH needs to be
* sent first. Else, skip the header i.e. xfer[0].
*/
int xfer_start_idx = (addr > 0xff) ? 0 : 1;
- size_t xfer_count = ARRAY_SIZE(xfer) - xfer_start_idx;
- int ret;
+ xfer_count -= xfer_start_idx;
ret = i2c_transfer(client->adapter, &xfer[xfer_start_idx], xfer_count);
if (likely(ret == xfer_count))
@@ -189,10 +169,46 @@ static int raydium_i2c_send(struct i2c_client *client,
{
int tries = 0;
int error;
+ u8 *tx_buf;
+ u8 reg_addr = addr & 0xff;
+
+ tx_buf = kmalloc(len + 1, GFP_KERNEL);
+ if (!tx_buf)
+ return -ENOMEM;
+
+ tx_buf[0] = reg_addr;
+ memcpy(tx_buf + 1, data, len);
do {
- error = raydium_i2c_xfer(client, addr, (void *)data, len,
- false);
+ struct raydium_bank_switch_header header = {
+ .cmd = RM_CMD_BANK_SWITCH,
+ .be_addr = cpu_to_be32(addr),
+ };
+
+ /*
+ * Perform as a single i2c_transfer transaction to ensure that
+ * no other I2C transactions are initiated on the bus to any
+ * other device in between. Initiating transacations to other
+ * devices after RM_CMD_BANK_SWITCH is sent is known to cause
+ * issues. This is also why regmap infrastructure cannot be used
+ * for this driver. Regmap handles page(bank) switch and reads
+ * as separate i2c_transfer() operations. This can result in
+ * problems if the Raydium device is on a shared I2C bus.
+ */
+ struct i2c_msg xfer[] = {
+ {
+ .addr = client->addr,
+ .len = sizeof(header),
+ .buf = (u8 *)&header,
+ },
+ {
+ .addr = client->addr,
+ .len = len + 1,
+ .buf = tx_buf,
+ },
+ };
+
+ error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
if (likely(!error))
return 0;
@@ -206,12 +222,46 @@ static int raydium_i2c_send(struct i2c_client *client,
static int raydium_i2c_read(struct i2c_client *client,
u32 addr, void *data, size_t len)
{
- size_t xfer_len;
int error;
while (len) {
- xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE);
- error = raydium_i2c_xfer(client, addr, data, xfer_len, true);
+ u8 reg_addr = addr & 0xff;
+ struct raydium_bank_switch_header header = {
+ .cmd = RM_CMD_BANK_SWITCH,
+ .be_addr = cpu_to_be32(addr),
+ };
+ size_t xfer_len = min_t(size_t, len, RM_MAX_READ_SIZE);
+
+ /*
+ * Perform as a single i2c_transfer transaction to ensure that
+ * no other I2C transactions are initiated on the bus to any
+ * other device in between. Initiating transacations to other
+ * devices after RM_CMD_BANK_SWITCH is sent is known to cause
+ * issues. This is also why regmap infrastructure cannot be used
+ * for this driver. Regmap handles page(bank) switch and writes
+ * as separate i2c_transfer() operations. This can result in
+ * problems if the Raydium device is on a shared I2C bus.
+ */
+ struct i2c_msg xfer[] = {
+ {
+ .addr = client->addr,
+ .len = sizeof(header),
+ .buf = (u8 *)&header,
+ },
+ {
+ .addr = client->addr,
+ .len = 1,
+ .buf = &reg_addr,
+ },
+ {
+ .addr = client->addr,
+ .len = xfer_len,
+ .buf = data,
+ .flags = I2C_M_RD,
+ }
+ };
+
+ error = raydium_i2c_xfer(client, addr, xfer, ARRAY_SIZE(xfer));
if (unlikely(error))
return error;
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 82920ff46f72..2e70c0b79444 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -20,10 +20,43 @@
#include <linux/clk.h>
#include <linux/io.h>
-#include <plat/adc.h>
-#include <plat/regs-adc.h>
+#include <linux/soc/samsung/s3c-adc.h>
#include <linux/platform_data/touchscreen-s3c2410.h>
+#define S3C2410_ADCCON (0x00)
+#define S3C2410_ADCTSC (0x04)
+#define S3C2410_ADCDLY (0x08)
+#define S3C2410_ADCDAT0 (0x0C)
+#define S3C2410_ADCDAT1 (0x10)
+#define S3C64XX_ADCUPDN (0x14)
+#define S3C2443_ADCMUX (0x18)
+#define S3C64XX_ADCCLRINT (0x18)
+#define S5P_ADCMUX (0x1C)
+#define S3C64XX_ADCCLRINTPNDNUP (0x20)
+
+/* ADCTSC Register Bits */
+#define S3C2443_ADCTSC_UD_SEN (1 << 8)
+#define S3C2410_ADCTSC_YM_SEN (1<<7)
+#define S3C2410_ADCTSC_YP_SEN (1<<6)
+#define S3C2410_ADCTSC_XM_SEN (1<<5)
+#define S3C2410_ADCTSC_XP_SEN (1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
+#define S3C2410_ADCTSC_AUTO_PST (1<<2)
+#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN (1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT0_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK (0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN (1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST (1<<14)
+#define S3C2410_ADCDAT1_XY_PST (0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK (0x03FF)
+
+
#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
#define INT_DOWN (0)
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index bda96762744e..b4e7bcbe9b91 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -26,6 +26,20 @@
#define ST1232_TS_NAME "st1232-ts"
#define ST1633_TS_NAME "st1633-ts"
+#define REG_STATUS 0x01 /* Device Status | Error Code */
+
+#define STATUS_NORMAL 0x00
+#define STATUS_INIT 0x01
+#define STATUS_ERROR 0x02
+#define STATUS_AUTO_TUNING 0x03
+#define STATUS_IDLE 0x04
+#define STATUS_POWER_DOWN 0x05
+
+#define ERROR_NONE 0x00
+#define ERROR_INVALID_ADDRESS 0x10
+#define ERROR_INVALID_VALUE 0x20
+#define ERROR_INVALID_PLATFORM 0x30
+
#define REG_XY_RESOLUTION 0x04
#define REG_XY_COORDINATES 0x12
#define ST_TS_MAX_FINGERS 10
@@ -47,7 +61,8 @@ struct st1232_ts_data {
u8 *read_buf;
};
-static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg)
+static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg,
+ unsigned int n)
{
struct i2c_client *client = ts->client;
struct i2c_msg msg[] = {
@@ -59,7 +74,7 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg)
{
.addr = client->addr,
.flags = I2C_M_RD | I2C_M_DMA_SAFE,
- .len = ts->read_buf_len,
+ .len = n,
.buf = ts->read_buf,
}
};
@@ -72,6 +87,22 @@ static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg)
return 0;
}
+static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
+{
+ unsigned int retries;
+ int error;
+
+ for (retries = 10; retries; retries--) {
+ error = st1232_ts_read_data(ts, REG_STATUS, 1);
+ if (!error && ts->read_buf[0] == (STATUS_NORMAL | ERROR_NONE))
+ return 0;
+
+ usleep_range(1000, 2000);
+ }
+
+ return -ENXIO;
+}
+
static int st1232_ts_read_resolution(struct st1232_ts_data *ts, u16 *max_x,
u16 *max_y)
{
@@ -79,14 +110,14 @@ static int st1232_ts_read_resolution(struct st1232_ts_data *ts, u16 *max_x,
int error;
/* select resolution register */
- error = st1232_ts_read_data(ts, REG_XY_RESOLUTION);
+ error = st1232_ts_read_data(ts, REG_XY_RESOLUTION, 3);
if (error)
return error;
buf = ts->read_buf;
- *max_x = ((buf[0] & 0x0070) << 4) | buf[1];
- *max_y = ((buf[0] & 0x0007) << 8) | buf[2];
+ *max_x = (((buf[0] & 0x0070) << 4) | buf[1]) - 1;
+ *max_y = (((buf[0] & 0x0007) << 8) | buf[2]) - 1;
return 0;
}
@@ -140,7 +171,7 @@ static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id)
int count;
int error;
- error = st1232_ts_read_data(ts, REG_XY_COORDINATES);
+ error = st1232_ts_read_data(ts, REG_XY_COORDINATES, ts->read_buf_len);
if (error)
goto out;
@@ -251,6 +282,11 @@ static int st1232_ts_probe(struct i2c_client *client,
input_dev->name = "st1232-touchscreen";
input_dev->id.bustype = BUS_I2C;
+ /* Wait until device is ready */
+ error = st1232_ts_wait_ready(ts);
+ if (error)
+ return error;
+
/* Read resolution from the chip */
error = st1232_ts_read_resolution(ts, &max_x, &max_y);
if (error) {