From 195e610bf7104d0dbe7e420e361dfb154694691d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Mart=C3=ADnez?= Date: Wed, 6 May 2015 16:33:40 -0700 Subject: Input: adp5589-keys - fix pull mask setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pull mask is created by looping each row (column) and building an 8-bit integer with the configuration. It is written byte-by-byte, when we reach the end of the rows (columns) or we're at the 3rd line (which finishes the first byte, since each pin is 2bits on the mask). However, this only works if we have at most 8 pins (2 bytes), which is not the case for the ADP5589. So, write the byte at each boundary (every 4 rows/columns). Signed-off-by: Guido Martínez Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5589-keys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index a45267729dfc..50bc0a0c598b 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -726,7 +726,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad) pull_mask |= val << (2 * (i & 0x3)); - if (i == 3 || i == kpad->var->max_row_num) { + if (i % 4 == 3 || i == kpad->var->max_row_num) { ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A) + (i >> 2), pull_mask); pull_mask = 0; @@ -746,7 +746,7 @@ static int adp5589_setup(struct adp5589_kpad *kpad) pull_mask |= val << (2 * (i & 0x3)); - if (i == 3 || i == kpad->var->max_col_num) { + if (i % 4 == 3 || i == kpad->var->max_col_num) { ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_C) + (i >> 2), pull_mask); -- cgit v1.2.3 From c615dcb6d13e6db3083507114fa3696be98d5211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20Mart=C3=ADnez?= Date: Wed, 6 May 2015 16:35:21 -0700 Subject: Input: adp5589-keys - fix event count mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The event mask was specified as 0xF (4 bits) when in reality is 0x1F (5 bits) in order to be capable of representing all FIFO length values from 0 to 16. This caused a problem: when the keypad reported 16 pending events the driver took it as 0, and did nothing. This in turn caused the keypad to re-issue the interrupt over and over again. Signed-off-by: Guido Martínez Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5589-keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 50bc0a0c598b..6ed83cf8b74e 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -180,7 +180,7 @@ #define LOGIC2_STAT (1 << 7) /* ADP5589 only */ #define LOGIC1_STAT (1 << 6) #define LOCK_STAT (1 << 5) /* ADP5589 only */ -#define KEC 0xF +#define KEC 0x1F /* PIN_CONFIG_D Register */ #define C4_EXTEND_CFG (1 << 6) /* RESET2 */ -- cgit v1.2.3 From 5f6f117c12a3fb25ecadd6dfcdd1a3a431269ade Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 6 May 2015 16:52:13 -0700 Subject: Input: goodix - check the 'buffer status' bit before reading data The MSB of the first byte read via I2C at the coordinates address indicates whether the data is valid or ready (called "buffer status" in the datasheets) when an interrupt is raised. Previously, this bit was ignored, which resulted in a lot of incorrect detections of "finger removed" events. Signed-off-by: Paul Cercueil Acked-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 3af16984d57c..0d93b1e5e28e 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -101,6 +101,9 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) return error; } + if (!(data[0] & 0x80)) + return -EAGAIN; + touch_num = data[0] & 0x0f; if (touch_num > ts->max_touch_num) return -EPROTO; -- cgit v1.2.3 From 8550b073716eda61329710bf133b8f5c25df40fa Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 May 2015 16:54:56 -0700 Subject: Input: samsung-keypad - constify platform_device_id The platform_device_id is not modified by the driver and core uses it as const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/samsung-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 6b9fdf6cf8e8..43e48dac7687 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -585,7 +585,7 @@ static const struct of_device_id samsung_keypad_dt_match[] = { MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); #endif -static struct platform_device_id samsung_keypad_driver_ids[] = { +static const struct platform_device_id samsung_keypad_driver_ids[] = { { .name = "samsung-keypad", .driver_data = KEYPAD_TYPE_SAMSUNG, -- cgit v1.2.3 From 3419e49a0efafc9577413a250f330de5e14e6705 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 6 May 2015 16:55:21 -0700 Subject: Input: s3c2410_ts - constify platform_device_id The platform_device_id is not modified by the driver and core uses it as const. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s3c2410_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index bdfa27dc097b..a4a103e1d11b 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -411,7 +411,7 @@ static const struct dev_pm_ops s3c_ts_pmops = { }; #endif -static struct platform_device_id s3cts_driver_ids[] = { +static const struct platform_device_id s3cts_driver_ids[] = { { "s3c2410-ts", 0 }, { "s3c2440-ts", 0 }, { "s3c64xx-ts", FEAT_PEN_IRQ }, -- cgit v1.2.3 From 8f6bcc97ab3f79b2f7f1fd59de8cd38af3535497 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 7 May 2015 22:24:58 -0700 Subject: Input: smtpe-ts - use msecs_to_jiffies() instead of HZ Use msecs_to_jiffies(20) instead of plain (HZ / 50), as the former is much more explicit about it's behavior. We want to schedule the task 20 mS from now, so make it explicit in the code. Signed-off-by: Marek Vasut Reviewed-by: Viresh Kumar Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/stmpe-ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index 2d5ff86b343f..702ad200d916 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -164,7 +164,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); /* start polling for touch_det to detect release */ - schedule_delayed_work(&ts->work, HZ / 50); + schedule_delayed_work(&ts->work, msecs_to_jiffies(20)); return IRQ_HANDLED; } -- cgit v1.2.3 From 9ceeb59c5f7e4c4612039323f4266cabb3baedfd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 7 May 2015 22:25:49 -0700 Subject: Input: smtpe-ts - wait 50mS until polling for pen-up Wait a little bit longer, 50mS instead of 20mS, until the driver starts polling for pen-up. The problematic behavior before this patch is applied is as follows. The behavior was observed on the STMPE610QTR controller. Upon a physical pen-down event, the touchscreen reports one set of x-y-p coordinates and a pen-down event. After that, the pen-up polling is triggered and since the controller is not ready yet, the polling mistakenly detects a pen-up event while the physical state is still such that the pen is down on the touch surface. The pen-up handling flushes the controller FIFO, so after that, all the samples in the controller are discarded. The controller becomes ready shortly after this bogus pen-up handling and does generate again a pen-down interrupt. This time, the controller contains x-y-p samples which all read as zero. Since pressure value is zero, this set of samples is effectively ignored by userland. In the end, the driver just bounces between pen-down and bogus pen-up handling, generating no useful results. Fix this by giving the controller a bit more time before polling it for pen-up. Signed-off-by: Marek Vasut Reviewed-by: Viresh Kumar Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/stmpe-ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index 702ad200d916..e4c31256a74d 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -164,7 +164,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN); /* start polling for touch_det to detect release */ - schedule_delayed_work(&ts->work, msecs_to_jiffies(20)); + schedule_delayed_work(&ts->work, msecs_to_jiffies(50)); return IRQ_HANDLED; } -- cgit v1.2.3 From c857ea9e1c8fd5dc684fbc99ecb50f540549f659 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 8 May 2015 15:59:57 -0700 Subject: Input: drv2667 - fix Kconfig error for help screen Fix the Kconfig for the drv2667 as there was a copy/paste error. Signed-off-by: Dan Murphy Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 4436ab1b9735..7838f1a06856 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -784,6 +784,6 @@ config INPUT_DRV2667_HAPTICS Say Y to enable support for the TI DRV2667 haptics driver. To compile this driver as a module, choose M here: the - module will be called drv260x-haptics. + module will be called drv2667-haptics. endif -- cgit v1.2.3 From 8a4dda79a383ed9b09aa3af3ef74941bec2ee042 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 8 May 2015 16:01:39 -0700 Subject: Input: ff-core - fix spelling mistake in ff-core Fix spelling of magnitude s/manginude/magnitude Signed-off-by: Dan Murphy Signed-off-by: Dmitry Torokhov --- drivers/input/ff-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index b81c88c43452..375d1ca14bd6 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -70,7 +70,7 @@ static int compat_effect(struct ff_device *ff, struct ff_effect *effect) return -EINVAL; /* - * calculate manginude of sine wave as average of rumble's + * calculate magnitude of sine wave as average of rumble's * 2/3 of strong magnitude and 1/3 of weak magnitude */ magnitude = effect->u.rumble.strong_magnitude / 3 + -- cgit v1.2.3 From 4d10da13467e223441d3b081eb70e91149ea5da9 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Fri, 8 May 2015 16:02:43 -0700 Subject: Input: add TI drv2665 haptics driver Add the TI drv2665 piezo haptic driver. This haptics IC requires the data to be streamed to the FIFO for continuous output. Datasheet can be found at: http://www.ti.com/product/drv2665 Signed-off-by: Dan Murphy Signed-off-by: Dmitry Torokhov --- .../devicetree/bindings/input/ti,drv2665.txt | 17 ++ drivers/input/misc/Kconfig | 11 + drivers/input/misc/Makefile | 1 + drivers/input/misc/drv2665.c | 322 +++++++++++++++++++++ 4 files changed, 351 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/ti,drv2665.txt create mode 100644 drivers/input/misc/drv2665.c diff --git a/Documentation/devicetree/bindings/input/ti,drv2665.txt b/Documentation/devicetree/bindings/input/ti,drv2665.txt new file mode 100644 index 000000000000..1ba97ac04305 --- /dev/null +++ b/Documentation/devicetree/bindings/input/ti,drv2665.txt @@ -0,0 +1,17 @@ +* Texas Instruments - drv2665 Haptics driver + +Required properties: + - compatible - "ti,drv2665" - DRV2665 + - reg - I2C slave address + - vbat-supply - Required supply regulator + +Example: + +haptics: haptics@59 { + compatible = "ti,drv2665"; + reg = <0x59>; + vbat-supply = <&vbat>; +}; + +For more product information please see the link below: +http://www.ti.com/product/drv2665 diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7838f1a06856..e5c4de279001 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -775,6 +775,17 @@ config INPUT_DRV260X_HAPTICS To compile this driver as a module, choose M here: the module will be called drv260x-haptics. +config INPUT_DRV2665_HAPTICS + tristate "TI DRV2665 haptics support" + depends on INPUT && I2C + select INPUT_FF_MEMLESS + select REGMAP_I2C + help + Say Y to enable support for the TI DRV2665 haptics driver. + + To compile this driver as a module, choose M here: the + module will be called drv2665-haptics. + config INPUT_DRV2667_HAPTICS tristate "TI DRV2667 haptics support" depends on INPUT && I2C diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 78ba4c1b8532..d3179472474d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o +obj-$(CONFIG_INPUT_DRV2665_HAPTICS) += drv2665.o obj-$(CONFIG_INPUT_DRV2667_HAPTICS) += drv2667.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o obj-$(CONFIG_INPUT_GPIO_BEEPER) += gpio-beeper.o diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c new file mode 100644 index 000000000000..0afaa33de07d --- /dev/null +++ b/drivers/input/misc/drv2665.c @@ -0,0 +1,322 @@ +/* + * DRV2665 haptics driver family + * + * Author: Dan Murphy + * + * Copyright: (C) 2015 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Contol registers */ +#define DRV2665_STATUS 0x00 +#define DRV2665_CTRL_1 0x01 +#define DRV2665_CTRL_2 0x02 +#define DRV2665_FIFO 0x0b + +/* Status Register */ +#define DRV2665_FIFO_FULL BIT(0) +#define DRV2665_FIFO_EMPTY BIT(1) + +/* Control 1 Register */ +#define DRV2665_25_VPP_GAIN 0x00 +#define DRV2665_50_VPP_GAIN 0x01 +#define DRV2665_75_VPP_GAIN 0x02 +#define DRV2665_100_VPP_GAIN 0x03 +#define DRV2665_DIGITAL_IN 0xfc +#define DRV2665_ANALOG_IN BIT(2) + +/* Control 2 Register */ +#define DRV2665_BOOST_EN BIT(1) +#define DRV2665_STANDBY BIT(6) +#define DRV2665_DEV_RST BIT(7) +#define DRV2665_5_MS_IDLE_TOUT 0x00 +#define DRV2665_10_MS_IDLE_TOUT 0x04 +#define DRV2665_15_MS_IDLE_TOUT 0x08 +#define DRV2665_20_MS_IDLE_TOUT 0x0c + +/** + * struct drv2665_data - + * @input_dev - Pointer to the input device + * @client - Pointer to the I2C client + * @regmap - Register map of the device + * @work - Work item used to off load the enable/disable of the vibration + * @regulator - Pointer to the regulator for the IC + */ +struct drv2665_data { + struct input_dev *input_dev; + struct i2c_client *client; + struct regmap *regmap; + struct work_struct work; + struct regulator *regulator; +}; + +/* 8kHz Sine wave to stream to the FIFO */ +static const u8 drv2665_sine_wave_form[] = { + 0x00, 0x10, 0x20, 0x2e, 0x3c, 0x48, 0x53, 0x5b, 0x61, 0x65, 0x66, + 0x65, 0x61, 0x5b, 0x53, 0x48, 0x3c, 0x2e, 0x20, 0x10, + 0x00, 0xf0, 0xe0, 0xd2, 0xc4, 0xb8, 0xad, 0xa5, 0x9f, 0x9b, 0x9a, + 0x9b, 0x9f, 0xa5, 0xad, 0xb8, 0xc4, 0xd2, 0xe0, 0xf0, 0x00, +}; + +static struct reg_default drv2665_reg_defs[] = { + { DRV2665_STATUS, 0x02 }, + { DRV2665_CTRL_1, 0x28 }, + { DRV2665_CTRL_2, 0x40 }, + { DRV2665_FIFO, 0x00 }, +}; + +static void drv2665_worker(struct work_struct *work) +{ + struct drv2665_data *haptics = + container_of(work, struct drv2665_data, work); + unsigned int read_buf; + int error; + + error = regmap_read(haptics->regmap, DRV2665_STATUS, &read_buf); + if (error) { + dev_err(&haptics->client->dev, + "Failed to read status: %d\n", error); + return; + } + + if (read_buf & DRV2665_FIFO_EMPTY) { + error = regmap_bulk_write(haptics->regmap, + DRV2665_FIFO, + drv2665_sine_wave_form, + ARRAY_SIZE(drv2665_sine_wave_form)); + if (error) { + dev_err(&haptics->client->dev, + "Failed to write FIFO: %d\n", error); + return; + } + } +} + +static int drv2665_haptics_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct drv2665_data *haptics = input_get_drvdata(input); + + schedule_work(&haptics->work); + + return 0; +} + +static void drv2665_close(struct input_dev *input) +{ + struct drv2665_data *haptics = input_get_drvdata(input); + int error; + + cancel_work_sync(&haptics->work); + + error = regmap_update_bits(haptics->regmap, + DRV2665_CTRL_2, DRV2665_STANDBY, 1); + if (error) + dev_err(&haptics->client->dev, + "Failed to enter standby mode: %d\n", error); +} + +static const struct reg_default drv2665_init_regs[] = { + { DRV2665_CTRL_2, 0 | DRV2665_10_MS_IDLE_TOUT }, + { DRV2665_CTRL_1, DRV2665_25_VPP_GAIN }, +}; + +static int drv2665_init(struct drv2665_data *haptics) +{ + int error; + + error = regmap_register_patch(haptics->regmap, + drv2665_init_regs, + ARRAY_SIZE(drv2665_init_regs)); + if (error) { + dev_err(&haptics->client->dev, + "Failed to write init registers: %d\n", + error); + return error; + } + + return 0; +} + +static const struct regmap_config drv2665_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = DRV2665_FIFO, + .reg_defaults = drv2665_reg_defs, + .num_reg_defaults = ARRAY_SIZE(drv2665_reg_defs), + .cache_type = REGCACHE_NONE, +}; + +static int drv2665_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct drv2665_data *haptics; + int error; + + haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL); + if (!haptics) + return -ENOMEM; + + haptics->regulator = devm_regulator_get(&client->dev, "vbat"); + if (IS_ERR(haptics->regulator)) { + error = PTR_ERR(haptics->regulator); + dev_err(&client->dev, + "unable to get regulator, error: %d\n", error); + return error; + } + + haptics->input_dev = devm_input_allocate_device(&client->dev); + if (!haptics->input_dev) { + dev_err(&client->dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + haptics->input_dev->name = "drv2665:haptics"; + haptics->input_dev->dev.parent = client->dev.parent; + haptics->input_dev->close = drv2665_close; + input_set_drvdata(haptics->input_dev, haptics); + input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE); + + error = input_ff_create_memless(haptics->input_dev, NULL, + drv2665_haptics_play); + if (error) { + dev_err(&client->dev, "input_ff_create() failed: %d\n", + error); + return error; + } + + INIT_WORK(&haptics->work, drv2665_worker); + + haptics->client = client; + i2c_set_clientdata(client, haptics); + + haptics->regmap = devm_regmap_init_i2c(client, &drv2665_regmap_config); + if (IS_ERR(haptics->regmap)) { + error = PTR_ERR(haptics->regmap); + dev_err(&client->dev, "Failed to allocate register map: %d\n", + error); + return error; + } + + error = drv2665_init(haptics); + if (error) { + dev_err(&client->dev, "Device init failed: %d\n", error); + return error; + } + + error = input_register_device(haptics->input_dev); + if (error) { + dev_err(&client->dev, "couldn't register input device: %d\n", + error); + return error; + } + + return 0; +} + +static int __maybe_unused drv2665_suspend(struct device *dev) +{ + struct drv2665_data *haptics = dev_get_drvdata(dev); + int ret = 0; + + mutex_lock(&haptics->input_dev->mutex); + + if (haptics->input_dev->users) { + ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, 1); + if (ret) { + dev_err(dev, "Failed to set standby mode\n"); + regulator_disable(haptics->regulator); + goto out; + } + + ret = regulator_disable(haptics->regulator); + if (ret) { + dev_err(dev, "Failed to disable regulator\n"); + regmap_update_bits(haptics->regmap, + DRV2665_CTRL_2, + DRV2665_STANDBY, 0); + } + } +out: + mutex_unlock(&haptics->input_dev->mutex); + return ret; +} + +static int __maybe_unused drv2665_resume(struct device *dev) +{ + struct drv2665_data *haptics = dev_get_drvdata(dev); + int ret = 0; + + mutex_lock(&haptics->input_dev->mutex); + + if (haptics->input_dev->users) { + ret = regulator_enable(haptics->regulator); + if (ret) { + dev_err(dev, "Failed to enable regulator\n"); + goto out; + } + + ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, 0); + if (ret) { + dev_err(dev, "Failed to unset standby mode\n"); + regulator_disable(haptics->regulator); + goto out; + } + + } + +out: + mutex_unlock(&haptics->input_dev->mutex); + return ret; +} + +static SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume); + +static const struct i2c_device_id drv2665_id[] = { + { "drv2665", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, drv2665_id); + +#ifdef CONFIG_OF +static const struct of_device_id drv2665_of_match[] = { + { .compatible = "ti,drv2665", }, + { } +}; +MODULE_DEVICE_TABLE(of, drv2665_of_match); +#endif + +static struct i2c_driver drv2665_driver = { + .probe = drv2665_probe, + .driver = { + .name = "drv2665-haptics", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(drv2665_of_match), + .pm = &drv2665_pm_ops, + }, + .id_table = drv2665_id, +}; +module_i2c_driver(drv2665_driver); + +MODULE_DESCRIPTION("TI DRV2665 haptics driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dan Murphy "); -- cgit v1.2.3 From 755bab5b804d4873001c608bda5f18ab6a2d3372 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 Apr 2015 13:36:59 -0700 Subject: Input: zforce - remove duplicated include Remove duplicated include for delay.h. Signed-off-by: Wei Yongjun Reviewed-by: Heiko Stuebner Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/zforce_ts.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 19880c7385e3..f58a196521a9 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 6dd063353f9317955a67bc23249eac43128f7ff7 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 16 Apr 2015 13:38:00 -0700 Subject: Input: soc_button_array - remove duplicated include Remove duplicated include for acpi.h. Signed-off-by: Wei Yongjun Signed-off-by: Dmitry Torokhov --- drivers/input/misc/soc_button_array.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index e8e010a85484..c14b82709b0f 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -18,7 +18,6 @@ #include #include #include -#include /* * Definition of buttons on the tablet. The ACPI index of each button -- cgit v1.2.3 From 67367fd259f26d15e7e3ec15d0d8b8ab5601bbbb Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 15 May 2015 13:45:40 -0700 Subject: Input: evdev - use kvfree() in evdev_release() Use kvfree() instead of open-coding it. Signed-off-by: Pekka Enberg Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a18f41b89b6a..9d35499faca4 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -422,10 +422,7 @@ static int evdev_release(struct inode *inode, struct file *file) evdev_detach_client(evdev, client); - if (is_vmalloc_addr(client)) - vfree(client); - else - kfree(client); + kvfree(client); evdev_close_device(evdev); -- cgit v1.2.3 From ee3514b2256ef6aaa3b9f353af88d831dd596d09 Mon Sep 17 00:00:00 2001 From: Evgeniy Dushistov Date: Fri, 15 May 2015 13:47:46 -0700 Subject: Input: max7359_keypad - do not set MAX7359_CFG_INTERRUPT flag In datasheet of max7359 there is the following description of this flag: 0 - INT cleared when FIFO empty, 1 - INT cleared after host read. In this mode, I2C should read FIFO until interrupt condition removed, or further INT may be lost. So, if we set this flag, we have to read FIFO until it becomes empty. But in interrupt we read FIFO just once. This lead to "keyboard" hang until reboot, if we press several keys, because of interrupt handler read just one "press" from FIFO and clear interrupt. Signed-off-by: Evgeniy A. Dushistov Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/max7359_keypad.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index faa6da53eba8..4e35904d65ad 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -166,7 +166,6 @@ static void max7359_close(struct input_dev *dev) static void max7359_initialize(struct i2c_client *client) { max7359_write_reg(client, MAX7359_REG_CONFIG, - MAX7359_CFG_INTERRUPT | /* Irq clears after host read */ MAX7359_CFG_KEY_RELEASE | /* Key release enable */ MAX7359_CFG_WAKEUP); /* Key press wakeup enable */ -- cgit v1.2.3 From 68aeee98eeb311958be4dfeb03f1da2d90a270d9 Mon Sep 17 00:00:00 2001 From: Evgeniy Dushistov Date: Fri, 15 May 2015 13:49:00 -0700 Subject: Input: max7359_keypad - switch to using matrix_keypad_build_keymap() max7359_build_keycode() does the same thing as matrix_keypad_build_keymap(), but the latter can also handle DT bindings. Tested on beagleboard-xm. Signed-off-by: Evgeniy A. Dushistov Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 1 + drivers/input/keyboard/max7359_keypad.c | 30 +++++++++--------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 106fbac7f8c5..4d75062a6206 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -367,6 +367,7 @@ config KEYBOARD_MAPLE config KEYBOARD_MAX7359 tristate "Maxim MAX7359 Key Switch Controller" + select INPUT_MATRIXKMAP depends on I2C help If you say yes here you get support for the Maxim MAX7359 Key diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 4e35904d65ad..5091133b7b8e 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -84,26 +84,6 @@ static int max7359_read_reg(struct i2c_client *client, int reg) return ret; } -static void max7359_build_keycode(struct max7359_keypad *keypad, - const struct matrix_keymap_data *keymap_data) -{ - struct input_dev *input_dev = keypad->input_dev; - int i; - - for (i = 0; i < keymap_data->keymap_size; i++) { - unsigned int key = keymap_data->keymap[i]; - unsigned int row = KEY_ROW(key); - unsigned int col = KEY_COL(key); - unsigned int scancode = MATRIX_SCAN_CODE(row, col, - MAX7359_ROW_SHIFT); - unsigned short keycode = KEY_VAL(key); - - keypad->keycodes[scancode] = keycode; - __set_bit(keycode, input_dev->keybit); - } - __clear_bit(KEY_RESERVED, input_dev->keybit); -} - /* runs in an IRQ thread -- can (and will!) sleep */ static irqreturn_t max7359_interrupt(int irq, void *dev_id) { @@ -232,7 +212,15 @@ static int max7359_probe(struct i2c_client *client, input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); - max7359_build_keycode(keypad, keymap_data); + error = matrix_keypad_build_keymap(keymap_data, NULL, + MAX7359_MAX_KEY_ROWS, + MAX7359_MAX_KEY_COLS, + keypad->keycodes, + input_dev); + if (error) { + dev_err(&client->dev, "failed to build keymap\n"); + return error; + } error = devm_request_threaded_irq(&client->dev, client->irq, NULL, max7359_interrupt, -- cgit v1.2.3 From 5f4eedef77307768a5ea59485aa518b991660142 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 May 2015 15:55:23 -0700 Subject: Input: twl4030-pwrbutton - pass the IRQF_ONESHOT flag Since commit 1c6c69525b40eb76de8adf039409722015927dc3 ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. So pass the IRQF_ONESHOT flag in this case. The semantic patch that makes this change is available in scripts/coccinelle/misc/irqf_oneshot.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index e98cc81a84c6..603fc2fadf05 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -71,7 +71,8 @@ static int twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->dev.parent = &pdev->dev; err = devm_request_threaded_irq(&pwr->dev, irq, NULL, powerbutton_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | + IRQF_ONESHOT, "twl4030_pwrbutton", pwr); if (err < 0) { dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err); -- cgit v1.2.3 From 6b36d8f6a2ef0e8d3bf52660554c476b926d2b22 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 May 2015 15:55:34 -0700 Subject: Input: retu-pwrbutton - pass the IRQF_ONESHOT flag Since commit 1c6c69525b40eb76de8adf039409722015927dc3 ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. So pass the IRQF_ONESHOT flag in this case. The semantic patch that makes this change is available in scripts/coccinelle/misc/irqf_oneshot.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/misc/retu-pwrbutton.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c index 0c8ac60e2639..30b459b6b344 100644 --- a/drivers/input/misc/retu-pwrbutton.c +++ b/drivers/input/misc/retu-pwrbutton.c @@ -63,7 +63,8 @@ static int retu_pwrbutton_probe(struct platform_device *pdev) input_set_drvdata(idev, rdev); error = devm_request_threaded_irq(&pdev->dev, irq, - NULL, retu_pwrbutton_irq, 0, + NULL, retu_pwrbutton_irq, + IRQF_ONESHOT, "retu-pwrbutton", idev); if (error) return error; -- cgit v1.2.3 From 4be01a2935fa3d745e023011cef3dd70e88f15f9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 May 2015 15:55:42 -0700 Subject: Input: twl6040-vibra - pass the IRQF_ONESHOT flag Since commit 1c6c69525b40eb76de8adf039409722015927dc3 ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. So pass the IRQF_ONESHOT flag in this case. The semantic patch that makes this change is available in scripts/coccinelle/misc/irqf_oneshot.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl6040-vibra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 0e0d094df2e6..ea63fad48de6 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -308,7 +308,8 @@ static int twl6040_vibra_probe(struct platform_device *pdev) mutex_init(&info->mutex); error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, - twl6040_vib_irq_handler, 0, + twl6040_vib_irq_handler, + IRQF_ONESHOT, "twl6040_irq_vib", info); if (error) { dev_err(info->dev, "VIB IRQ request failed: %d\n", error); -- cgit v1.2.3 From ca8ff6ac455d6138be7228afd8590c6ddc46524f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 15 May 2015 15:55:52 -0700 Subject: Input: wm831x-on - pass the IRQF_ONESHOT flag Since commit 1c6c69525b40eb76de8adf039409722015927dc3 ("genirq: Reject bogus threaded irq requests") threaded IRQs without a primary handler need to be requested with IRQF_ONESHOT, otherwise the request will fail. So pass the IRQF_ONESHOT flag in this case. The semantic patch that makes this change is available in scripts/coccinelle/misc/irqf_oneshot.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wm831x-on.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index 59d4f7bcb4a3..1b44de265a0a 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -99,7 +99,8 @@ static int wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->dev.parent = &pdev->dev; ret = request_threaded_irq(irq, NULL, wm831x_on_irq, - IRQF_TRIGGER_RISING, "wm831x_on", + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "wm831x_on", wm831x_on); if (ret < 0) { dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); -- cgit v1.2.3 From ec8beff9647897659df5e1ad120a00cfc8c7a98e Mon Sep 17 00:00:00 2001 From: Shailendra Verma Date: Mon, 18 May 2015 10:44:33 -0700 Subject: Input: fix typo in comment to input_handler_for_each_handle() Signed-off-by: Shailendra Verma Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index cc357f1516a7..f31578423636 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2262,7 +2262,7 @@ EXPORT_SYMBOL(input_unregister_handler); * * Iterate over @bus's list of devices, and call @fn for each, passing * it @data and stop when @fn returns a non-zero value. The function is - * using RCU to traverse the list and therefore may be usind in atonic + * using RCU to traverse the list and therefore may be using in atomic * contexts. The @fn callback is invoked from RCU critical section and * thus must not sleep. */ -- cgit v1.2.3 From 4e3e4629e4c6ef755ce246e4d848eaad6eec7080 Mon Sep 17 00:00:00 2001 From: Shailendra Verma Date: Mon, 18 May 2015 10:45:58 -0700 Subject: Input: ff-core - fix typo in comment to input_ff_erase() Signed-off-by: Shailendra Verma Signed-off-by: Dmitry Torokhov --- drivers/input/ff-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 375d1ca14bd6..8f4a30fccbb6 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -213,7 +213,7 @@ static int erase_effect(struct input_dev *dev, int effect_id, /** * input_ff_erase - erase a force-feedback effect from device * @dev: input device to erase effect from - * @effect_id: id of the ffect to be erased + * @effect_id: id of the effect to be erased * @file: purported owner of the request * * This function erases a force-feedback effect from specified device. -- cgit v1.2.3 From aab9cf7b0349b2f6f3d8a32d3f2414981777ebdc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:38:33 -0700 Subject: Input: alps - change alps_decode_rushmore to do all decoding itself Change alps_decode_rushmore to do all decoding itself, rather then relying on alps_decode_pinnacle and then overriding some fields + or-ing in some bits. This is a preparation patch for modifying the decode functions to properly differentiate between position and bitmap packets. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 15d6bffdea77..f4ba73b81d31 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -597,13 +597,25 @@ static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p, struct psmouse *psmouse) { - alps_decode_pinnacle(f, p, psmouse); - - /* Rushmore's packet decode has a bit difference with Pinnacle's */ + f->first_mp = !!(p[4] & 0x40); f->is_mp = !!(p[5] & 0x40); + f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; - f->x_map |= (p[5] & 0x10) << 11; - f->y_map |= (p[5] & 0x20) << 6; + f->x_map = ((p[5] & 0x10) << 11) | + ((p[4] & 0x7e) << 8) | + ((p[1] & 0x7f) << 2) | + ((p[0] & 0x30) >> 4); + f->y_map = ((p[5] & 0x20) << 6) | + ((p[3] & 0x70) << 4) | + ((p[2] & 0x7f) << 1) | + (p[4] & 0x01); + + f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | + ((p[0] & 0x30) >> 4); + f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); + f->pressure = p[5] & 0x7f; + + alps_decode_buttons_v3(f, p); return 0; } -- cgit v1.2.3 From a839cd579b64e41779a24c691d0c88c6a16c63e0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:39:21 -0700 Subject: Input: alps - only set fields that are actually present Pinnacle / Rushmore packets contain either position info, or bitmap info, never both. So far we've in essence been storing garbage in the position / bitmap fields of the fields struct when decoding a bitmap / pos packet. We've been relying on the following sequence to get away with this: 1) Decode bitmap packet 2) Process bitmap packet 3) Decode position packet 4) Use position / button info This patch allows us to change this sequence, which will allow using the position info when processing the bitmap for more accurate results. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 62 ++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f4ba73b81d31..942ee08ce6b4 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -576,20 +576,22 @@ static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p, f->first_mp = !!(p[4] & 0x40); f->is_mp = !!(p[0] & 0x40); - f->fingers = (p[5] & 0x3) + 1; - f->x_map = ((p[4] & 0x7e) << 8) | - ((p[1] & 0x7f) << 2) | - ((p[0] & 0x30) >> 4); - f->y_map = ((p[3] & 0x70) << 4) | - ((p[2] & 0x7f) << 1) | - (p[4] & 0x01); - - f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | - ((p[0] & 0x30) >> 4); - f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); - f->pressure = p[5] & 0x7f; + if (f->is_mp) { + f->fingers = (p[5] & 0x3) + 1; + f->x_map = ((p[4] & 0x7e) << 8) | + ((p[1] & 0x7f) << 2) | + ((p[0] & 0x30) >> 4); + f->y_map = ((p[3] & 0x70) << 4) | + ((p[2] & 0x7f) << 1) | + (p[4] & 0x01); + } else { + f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | + ((p[0] & 0x30) >> 4); + f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); + f->pressure = p[5] & 0x7f; - alps_decode_buttons_v3(f, p); + alps_decode_buttons_v3(f, p); + } return 0; } @@ -600,22 +602,24 @@ static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p, f->first_mp = !!(p[4] & 0x40); f->is_mp = !!(p[5] & 0x40); - f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; - f->x_map = ((p[5] & 0x10) << 11) | - ((p[4] & 0x7e) << 8) | - ((p[1] & 0x7f) << 2) | - ((p[0] & 0x30) >> 4); - f->y_map = ((p[5] & 0x20) << 6) | - ((p[3] & 0x70) << 4) | - ((p[2] & 0x7f) << 1) | - (p[4] & 0x01); - - f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | - ((p[0] & 0x30) >> 4); - f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); - f->pressure = p[5] & 0x7f; - - alps_decode_buttons_v3(f, p); + if (f->is_mp) { + f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1; + f->x_map = ((p[5] & 0x10) << 11) | + ((p[4] & 0x7e) << 8) | + ((p[1] & 0x7f) << 2) | + ((p[0] & 0x30) >> 4); + f->y_map = ((p[5] & 0x20) << 6) | + ((p[3] & 0x70) << 4) | + ((p[2] & 0x7f) << 1) | + (p[4] & 0x01); + } else { + f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | + ((p[0] & 0x30) >> 4); + f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); + f->pressure = p[5] & 0x7f; + + alps_decode_buttons_v3(f, p); + } return 0; } -- cgit v1.2.3 From 44b77f38dce59f57a679083df12509deab02cfcc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:40:06 -0700 Subject: Input: alps - decode the position packet first We should decode the position packet before the packet with the bitmap data. This way we can use the more accurate position info in process_bitmap() to get better results. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 942ee08ce6b4..d1488db6d149 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -688,24 +688,17 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) */ if (f->is_mp) { fingers = f->fingers; + /* + * Bitmap processing uses position packet's coordinate + * data, so we need to do decode it first. + */ + priv->decode_fields(f, priv->multi_data, psmouse); + if (priv->proto_version == ALPS_PROTO_V3 || priv->proto_version == ALPS_PROTO_V3_RUSHMORE) { if (alps_process_bitmap(priv, f) == 0) fingers = 0; /* Use st data */ - - /* Now process position packet */ - priv->decode_fields(f, priv->multi_data, - psmouse); } else { - /* - * Because Dolphin uses position packet's - * coordinate data as Pt1 and uses it to - * calculate Pt2, so we need to do position - * packet decode first. - */ - priv->decode_fields(f, priv->multi_data, - psmouse); - /* * Since Dolphin's finger number is reliable, * there is no need to compare with bmap_fn. @@ -873,6 +866,14 @@ static void alps_process_packet_v4(struct psmouse *psmouse) priv->multi_data[offset] = packet[6]; priv->multi_data[offset + 1] = packet[7]; + f->left = !!(packet[4] & 0x01); + f->right = !!(packet[4] & 0x02); + + f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | + ((packet[0] & 0x30) >> 4); + f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); + f->pressure = packet[5] & 0x7f; + if (++priv->multi_packet > 2) { priv->multi_packet = 0; @@ -887,14 +888,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) f->fingers = alps_process_bitmap(priv, f); } - f->left = !!(packet[4] & 0x01); - f->right = !!(packet[4] & 0x02); - - f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) | - ((packet[0] & 0x30) >> 4); - f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); - f->pressure = packet[5] & 0x7f; - alps_report_semi_mt_data(psmouse, f->fingers); } -- cgit v1.2.3 From 4dd265730710bd881c45d6ccf41050c3738ffccd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:41:10 -0700 Subject: Input: alps - use more accurate coordinates for first touch in semi-mt mode All alps semi-mt touchpads give us the following data when 2 (or more) fingers are touching: 1 more or less accurate touch for the first finger down, and a bitmap with columns and rows in which 1 or more fingers are seen resulting in a crude (low res) bounding box. So far for v3, rushmore and v4 touchpads we've been reporting the coordinates of 2 opposite corners of the box when 2 fingers are touching. Ignoring the much better resolution data given in the normal position packet. This commit actually uses this data for the first touch, figures out which corner of the bounding box is closest to the first touch, and reports the coordinates of the opposite corner for the second touch, resulting in much better data for the first touch and for the single touch pointer-emulation events. This approach is similar to the one in alps_process_bitmap_dolphin, that function takes the single accurate touch info, calculates the distance to the center of the bounding box, and then puts the 2nd touch mirrored to the center. The downside of that approach is that if both touches move slowly in the same direction, the bounding box will stay the same for a while (as it is low res) and the second touch will thus been seen moving in the opposite direction until the bounding box actually changes, and then the second touch snaps to its new position resulting in a saw tooth pattern in the coordinates for the second touch, hence this new approach. This commit fixes 2 finger scrolling being choppy / jumpy on these touchpads. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 59 ++++++++++++++++++++++++++++++++++++++++------ drivers/input/mouse/alps.h | 1 + 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index d1488db6d149..220acb63ffd7 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -388,9 +388,10 @@ static void alps_get_bitmap_points(unsigned int map, static int alps_process_bitmap(struct alps_data *priv, struct alps_fields *fields) { - int i, fingers_x = 0, fingers_y = 0, fingers; + int i, fingers_x = 0, fingers_y = 0, fingers, closest; struct alps_bitmap_point x_low = {0,}, x_high = {0,}; struct alps_bitmap_point y_low = {0,}, y_high = {0,}; + struct input_mt_pos corner[4]; if (!fields->x_map || !fields->y_map) return 0; @@ -421,26 +422,69 @@ static int alps_process_bitmap(struct alps_data *priv, y_high.num_bits = max(i, 1); } - fields->mt[0].x = + /* top-left corner */ + corner[0].x = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / (2 * (priv->x_bits - 1)); - fields->mt[0].y = + corner[0].y = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / (2 * (priv->y_bits - 1)); - fields->mt[1].x = + /* top-right corner */ + corner[1].x = (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) / (2 * (priv->x_bits - 1)); - fields->mt[1].y = + corner[1].y = + (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / + (2 * (priv->y_bits - 1)); + + /* bottom-right corner */ + corner[2].x = + (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) / + (2 * (priv->x_bits - 1)); + corner[2].y = + (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / + (2 * (priv->y_bits - 1)); + + /* bottom-left corner */ + corner[3].x = + (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / + (2 * (priv->x_bits - 1)); + corner[3].y = (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / (2 * (priv->y_bits - 1)); /* y-bitmap order is reversed, except on rushmore */ if (priv->proto_version != ALPS_PROTO_V3_RUSHMORE) { - fields->mt[0].y = priv->y_max - fields->mt[0].y; - fields->mt[1].y = priv->y_max - fields->mt[1].y; + for (i = 0; i < 4; i++) + corner[i].y = priv->y_max - corner[i].y; + } + + /* + * We only select a corner for the second touch once per 2 finger + * touch sequence to avoid the chosen corner (and thus the coordinates) + * jumping around when the first touch is in the middle. + */ + if (priv->second_touch == -1) { + /* Find corner closest to our st coordinates */ + closest = 0x7fffffff; + for (i = 0; i < 4; i++) { + int dx = fields->st.x - corner[i].x; + int dy = fields->st.y - corner[i].y; + int distance = dx * dx + dy * dy; + + if (distance < closest) { + priv->second_touch = i; + closest = distance; + } + } + /* And select the opposite corner to use for the 2nd touch */ + priv->second_touch = (priv->second_touch + 2) % 4; } + fields->mt[0] = fields->st; + fields->mt[1] = corner[priv->second_touch]; + return fingers; } @@ -477,6 +521,7 @@ static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers) f->mt[0].x = f->st.x; f->mt[0].y = f->st.y; fingers = f->pressure > 0 ? 1 : 0; + priv->second_touch = -1; } alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2); diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 6dfdccc3a7c6..d37f814dc447 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -278,6 +278,7 @@ struct alps_data { int prev_fin; int multi_packet; + int second_touch; unsigned char multi_data[6]; struct alps_fields f; u8 quirks; -- cgit v1.2.3 From 1662c03387a777be0a00efaf8665de77bc898158 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:42:15 -0700 Subject: Input: alps - do not use input-mt finger tracking for semi-mt devices With the recent process_bitmap() changes all semi-mt devices always report the first finger down in slot 0, so stop using input-mt finger tracking for these. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 220acb63ffd7..f066761e8985 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -524,7 +524,11 @@ static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers) priv->second_touch = -1; } - alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2); + if (fingers >= 1) + alps_set_slot(dev, 0, f->mt[0].x, f->mt[0].y); + if (fingers >= 2) + alps_set_slot(dev, 1, f->mt[1].x, f->mt[1].y); + input_mt_sync_frame(dev); input_mt_report_finger_count(dev, fingers); @@ -2826,7 +2830,7 @@ static void alps_set_abs_params_mt(struct alps_data *priv, input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | - INPUT_MT_TRACK | INPUT_MT_SEMI_MT); + INPUT_MT_SEMI_MT); } static void alps_set_abs_params_v7(struct alps_data *priv, -- cgit v1.2.3 From 688ea364b2e73ae4d757e550ec06663a4903b334 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:42:50 -0700 Subject: Input: alps - rename alps_set_abs_params_mt to alps_set_abs_params_semi_mt Rename alps_set_abs_params_mt to alps_set_abs_params_semi_mt, to make it clear that it is only (to be) used for semi-mt devices. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f066761e8985..e9e13cd026d2 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -159,8 +159,8 @@ static const struct alps_protocol_info alps_v8_protocol_data = { static void alps_set_abs_params_st(struct alps_data *priv, struct input_dev *dev1); -static void alps_set_abs_params_mt(struct alps_data *priv, - struct input_dev *dev1); +static void alps_set_abs_params_semi_mt(struct alps_data *priv, + struct input_dev *dev1); static void alps_set_abs_params_v7(struct alps_data *priv, struct input_dev *dev1); static void alps_set_abs_params_ss4_v2(struct alps_data *priv, @@ -2606,7 +2606,7 @@ static int alps_set_protocol(struct psmouse *psmouse, case ALPS_PROTO_V3: priv->hw_init = alps_hw_init_v3; priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; + priv->set_abs_params = alps_set_abs_params_semi_mt; priv->decode_fields = alps_decode_pinnacle; priv->nibble_commands = alps_v3_nibble_commands; priv->addr_command = PSMOUSE_CMD_RESET_WRAP; @@ -2615,7 +2615,7 @@ static int alps_set_protocol(struct psmouse *psmouse, case ALPS_PROTO_V3_RUSHMORE: priv->hw_init = alps_hw_init_rushmore_v3; priv->process_packet = alps_process_packet_v3; - priv->set_abs_params = alps_set_abs_params_mt; + priv->set_abs_params = alps_set_abs_params_semi_mt; priv->decode_fields = alps_decode_rushmore; priv->nibble_commands = alps_v3_nibble_commands; priv->addr_command = PSMOUSE_CMD_RESET_WRAP; @@ -2631,7 +2631,7 @@ static int alps_set_protocol(struct psmouse *psmouse, case ALPS_PROTO_V4: priv->hw_init = alps_hw_init_v4; priv->process_packet = alps_process_packet_v4; - priv->set_abs_params = alps_set_abs_params_mt; + priv->set_abs_params = alps_set_abs_params_semi_mt; priv->nibble_commands = alps_v4_nibble_commands; priv->addr_command = PSMOUSE_CMD_DISABLE; break; @@ -2640,7 +2640,7 @@ static int alps_set_protocol(struct psmouse *psmouse, priv->hw_init = alps_hw_init_dolphin_v1; priv->process_packet = alps_process_touchpad_packet_v3_v5; priv->decode_fields = alps_decode_dolphin; - priv->set_abs_params = alps_set_abs_params_mt; + priv->set_abs_params = alps_set_abs_params_semi_mt; priv->nibble_commands = alps_v3_nibble_commands; priv->addr_command = PSMOUSE_CMD_RESET_WRAP; priv->x_bits = 23; @@ -2822,8 +2822,8 @@ static void alps_set_abs_params_mt_common(struct alps_data *priv, set_bit(BTN_TOOL_QUADTAP, dev1->keybit); } -static void alps_set_abs_params_mt(struct alps_data *priv, - struct input_dev *dev1) +static void alps_set_abs_params_semi_mt(struct alps_data *priv, + struct input_dev *dev1) { alps_set_abs_params_mt_common(priv, dev1); input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); -- cgit v1.2.3 From dccf1dd8458236a28552510b83a06a8cc0f1c473 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 14:43:09 -0700 Subject: Input: alps - use the generic process_bitmap function for v5 touchpads Now that the generic process_bitmap function has been improved to offer accurate coordinates for the first touch we can use it for v5 (dolphin) touchpads too. Besides being a nice code cleanup this also fixes the saw tooth pattern in the coordinates for the second touch the dolphin specific version had. Signed-off-by: Hans de Goede Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/alps.c | 74 ++++++++-------------------------------------- 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index e9e13cd026d2..4e1af89c7749 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -302,53 +302,6 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) input_sync(dev); } -/* - * Process bitmap data for V5 protocols. Return value is null. - * - * The bitmaps don't have enough data to track fingers, so this function - * only generates points representing a bounding box of at most two contacts. - * These two points are returned in fields->mt. - */ -static void alps_process_bitmap_dolphin(struct alps_data *priv, - struct alps_fields *fields) -{ - int box_middle_x, box_middle_y; - unsigned int x_map, y_map; - unsigned char start_bit, end_bit; - unsigned char x_msb, x_lsb, y_msb, y_lsb; - - x_map = fields->x_map; - y_map = fields->y_map; - - if (!x_map || !y_map) - return; - - /* Get Most-significant and Least-significant bit */ - x_msb = fls(x_map); - x_lsb = ffs(x_map); - y_msb = fls(y_map); - y_lsb = ffs(y_map); - - /* Most-significant bit should never exceed max sensor line number */ - if (x_msb > priv->x_bits || y_msb > priv->y_bits) - return; - - if (fields->fingers > 1) { - start_bit = priv->x_bits - x_msb; - end_bit = priv->x_bits - x_lsb; - box_middle_x = (priv->x_max * (start_bit + end_bit)) / - (2 * (priv->x_bits - 1)); - - start_bit = y_lsb - 1; - end_bit = y_msb - 1; - box_middle_y = (priv->y_max * (start_bit + end_bit)) / - (2 * (priv->y_bits - 1)); - fields->mt[0] = fields->st; - fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x; - fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y; - } -} - static void alps_get_bitmap_points(unsigned int map, struct alps_bitmap_point *low, struct alps_bitmap_point *high, @@ -376,7 +329,7 @@ static void alps_get_bitmap_points(unsigned int map, } /* - * Process bitmap data from v3 and v4 protocols. Returns the number of + * Process bitmap data from semi-mt protocols. Returns the number of * fingers detected. A return value of 0 means at least one of the * bitmaps was empty. * @@ -454,8 +407,15 @@ static int alps_process_bitmap(struct alps_data *priv, (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) / (2 * (priv->y_bits - 1)); - /* y-bitmap order is reversed, except on rushmore */ - if (priv->proto_version != ALPS_PROTO_V3_RUSHMORE) { + /* x-bitmap order is reversed on v5 touchpads */ + if (priv->proto_version == ALPS_PROTO_V5) { + for (i = 0; i < 4; i++) + corner[i].x = priv->x_max - corner[i].x; + } + + /* y-bitmap order is reversed on v3 and v4 touchpads */ + if (priv->proto_version == ALPS_PROTO_V3 || + priv->proto_version == ALPS_PROTO_V4) { for (i = 0; i < 4; i++) corner[i].y = priv->y_max - corner[i].y; } @@ -742,18 +702,8 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse) * data, so we need to do decode it first. */ priv->decode_fields(f, priv->multi_data, psmouse); - - if (priv->proto_version == ALPS_PROTO_V3 || - priv->proto_version == ALPS_PROTO_V3_RUSHMORE) { - if (alps_process_bitmap(priv, f) == 0) - fingers = 0; /* Use st data */ - } else { - /* - * Since Dolphin's finger number is reliable, - * there is no need to compare with bmap_fn. - */ - alps_process_bitmap_dolphin(priv, f); - } + if (alps_process_bitmap(priv, f) == 0) + fingers = 0; /* Use st data */ } else { priv->multi_packet = 0; } -- cgit v1.2.3 From c37f6d3879634ca44ef93659690bb1732bbfaab9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 15 Apr 2015 10:31:10 -0700 Subject: Input: atmel_mxt_ts - use BIT() macro when reporting button state This makes the intent a tad more clear. Reviewed-by: Javier Martinez Canillas Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 40b98dda8f38..dfc7309e3d38 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -726,15 +726,15 @@ static void mxt_input_button(struct mxt_data *data, u8 *message) { struct input_dev *input = data->input_dev; const struct mxt_platform_data *pdata = data->pdata; - bool button; int i; - /* Active-low switch */ for (i = 0; i < pdata->t19_num_keys; i++) { if (pdata->t19_keymap[i] == KEY_RESERVED) continue; - button = !(message[1] & (1 << i)); - input_report_key(input, pdata->t19_keymap[i], button); + + /* Active-low switch */ + input_report_key(input, pdata->t19_keymap[i], + !(message[1] & BIT(i))); } } -- cgit v1.2.3 From b53d750884b26561a3e37f1a49775540120930e5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 14 Apr 2015 17:46:43 -0700 Subject: Input: cyapa - do not set otherwise unused variable As the name suggests, always_unused argument in cyapa_gen3_set_power_mode() is never used, so there is no reason for setting it to 0. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa_gen3.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 1e2291c378fe..3faf01c1b191 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -950,14 +950,13 @@ static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode) * Device power mode can only be set when device is in operational mode. */ static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode, - u16 always_unused) + u16 always_unused) { int ret; u8 power; int tries; u16 sleep_time; - always_unused = 0; if (cyapa->state != CYAPA_STATE_OP) return 0; -- cgit v1.2.3 From e465bf6fc55d5ce21fb45a75c3fa613505e6be20 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 May 2015 16:06:49 -0700 Subject: DT: i2c: Deprecate adi,adxl34x compatible string DT nodes should use the more specific adi,adxl345 and adi,adxl346 compatible values instead. As the ADXL346 is backward-compatible with the ADXL345, ADXL346 nodes must list both adi,adxl346 and adi,adxl345, in that order. Signed-off-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- Documentation/devicetree/bindings/i2c/trivial-devices.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index aaa8325004d2..03db59125569 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -19,8 +19,7 @@ adi,adt7475 +/-1C TDM Extended Temp Range I.C adi,adt7476 +/-1C TDM Extended Temp Range I.C adi,adt7490 +/-1C TDM Extended Temp Range I.C adi,adxl345 Three-Axis Digital Accelerometer -adi,adxl346 Three-Axis Digital Accelerometer -adi,adxl34x Three-Axis Digital Accelerometer +adi,adxl346 Three-Axis Digital Accelerometer (backward-compatib