From 195e610bf7104d0dbe7e420e361dfb154694691d Mon Sep 17 00:00:00 2001 From: Guido Martínez 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: Guido Martínez 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-compatibility value "adi,adxl345" must be listed too) at,24c08 i2c serial eeprom (24cxx) atmel,24c00 i2c serial eeprom (24cxx) atmel,24c01 i2c serial eeprom (24cxx) -- cgit v1.2.3 From 3a38958d2477b718d1011fb88c24c4f264ee9700 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 21 May 2015 16:07:37 -0700 Subject: Input: adxl34x - add OF match support The I2C subsystem can match devices without explicit OF support based on the part of their compatible property after the comma. However, this mechanism uses the first compatible value only. For adxl34x OF device nodes the compatible property will contain the more specific "adi,adxl345" or "adi,adxl346" value first. This prevents the device node from being matched with the adxl34x driver. Fix this by adding an OF match table with an "adi,adxl345" compatible entry. There's no need to add the "adi,adxl346" entry as the ADXL346 is backward-compatible with the ADXL345 with differences handled by runtime detection of the device model. Signed-off-by: Laurent Pinchart Reviewed-by: Wolfram Sang Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- drivers/input/misc/adxl34x-i2c.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 470bfd6f0830..bdb5d03b296e 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -10,6 +10,7 @@ #include /* BUS_I2C */ #include #include +#include #include #include #include "adxl34x.h" @@ -135,11 +136,31 @@ static const struct i2c_device_id adxl34x_id[] = { MODULE_DEVICE_TABLE(i2c, adxl34x_id); +#ifdef CONFIG_OF +static const struct of_device_id adxl34x_of_id[] = { + /* + * The ADXL346 is backward-compatible with the ADXL345. Differences are + * handled by runtime detection of the device model, there's thus no + * need for listing the "adi,adxl346" compatible value explicitly. + */ + { .compatible = "adi,adxl345", }, + /* + * Deprecated, DT nodes should use one or more of the device-specific + * compatible values "adi,adxl345" and "adi,adxl346". + */ + { .compatible = "adi,adxl34x", }, + { } +}; + +MODULE_DEVICE_TABLE(of, adxl34x_of_id); +#endif + static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", .owner = THIS_MODULE, .pm = &adxl34x_i2c_pm, + .of_match_table = of_match_ptr(adxl34x_of_id), }, .probe = adxl34x_i2c_probe, .remove = adxl34x_i2c_remove, -- cgit v1.2.3 From bde304575f3ecaa9570a9329196dffaadf3adafa Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Fri, 22 May 2015 09:56:29 -0700 Subject: Input: sentelic - use "static inline" instead of "inline" gcc-5 defaults to gnu11 which used c99 inline semantics in c99 'inline' is not externally visible unlike gnu89, therefore we use 'static inline' which has same semantics between gnu89 and c99 Signed-off-by: Khem Raj Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/sentelic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h index aa697ece405b..42df9e3beae8 100644 --- a/drivers/input/mouse/sentelic.h +++ b/drivers/input/mouse/sentelic.h @@ -123,11 +123,11 @@ struct fsp_data { extern int fsp_detect(struct psmouse *psmouse, bool set_properties); extern int fsp_init(struct psmouse *psmouse); #else -inline int fsp_detect(struct psmouse *psmouse, bool set_properties) +static inline int fsp_detect(struct psmouse *psmouse, bool set_properties) { return -ENOSYS; } -inline int fsp_init(struct psmouse *psmouse) +static inline int fsp_init(struct psmouse *psmouse) { return -ENOSYS; } -- cgit v1.2.3 From 25d238b2260973bfca0b82181824340c7aeae45a Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Fri, 22 May 2015 09:58:30 -0700 Subject: Input: update email-id of Rajeev Kumar rajeev-dlh.kumar@st.com email-id doesn't exist anymore as I have left the company. Signed-off-by: Rajeev Kumar Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/spear-keyboard.c | 2 +- include/linux/platform_data/keyboard-spear.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index f42a543db043..623d451767e3 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -3,7 +3,7 @@ * Based on omap-keypad driver * * Copyright (C) 2010 ST Microelectronics - * Rajeev Kumar + * Rajeev Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/include/linux/platform_data/keyboard-spear.h b/include/linux/platform_data/keyboard-spear.h index 9248e3a7e333..5e3ff653900c 100644 --- a/include/linux/platform_data/keyboard-spear.h +++ b/include/linux/platform_data/keyboard-spear.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 ST Microelectronics - * Rajeev Kumar + * Rajeev Kumar * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any -- cgit v1.2.3 From f91a3f08b741e3c5ecf501c160e51f6032718f52 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 22 May 2015 13:09:11 -0700 Subject: Input: stmpe-ts - fix automatic module loading When STMPE is instantiated via device tree individual MFD cells rae formed with OF modaliases, not platform modaliases, and so we need to add OF device table to the driver if we want it to load automatically: of:Nstmpe_touchscreenTCst,stmpe-ts Reported-by: Heiner Kallweit Tested-by: Heiner Kallweit Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/stmpe-ts.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index e4c31256a74d..e4977c6250f3 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -383,13 +383,21 @@ static int stmpe_ts_remove(struct platform_device *pdev) static struct platform_driver stmpe_ts_driver = { .driver = { - .name = STMPE_TS_NAME, - }, + .name = STMPE_TS_NAME, + }, .probe = stmpe_input_probe, .remove = stmpe_ts_remove, }; module_platform_driver(stmpe_ts_driver); +#ifdef CONFIG_OF +static const struct of_device_id stmpe_ts_ids[] = { + { .compatible = "st,stmpe-ts", }, + { }, +}; +MODULE_DEVICE_TABLE(of, stmpe_ts_ids); +#endif + MODULE_AUTHOR("Luotao Fu "); MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e4b88e19897f1039fd83f1630517becafc0dd163 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 22 May 2015 13:44:33 -0700 Subject: Input: stmpe-ts - enforce device tree only mode The STMPE MFD is only used with device tree configured systems (and STMPE MFD core depends on OF), so force the configuration to come from device tree only. Tested-by: Heiner Kallweit Reviewed-by: Marek Vasut Acked-by: Lee Jones Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 1 + drivers/input/touchscreen/stmpe-ts.c | 29 ++++-------------------- include/linux/mfd/stmpe.h | 44 ------------------------------------ 3 files changed, 6 insertions(+), 68 deletions(-) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 547f67d65372..a398d636ca39 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -958,6 +958,7 @@ config TOUCHSCREEN_ST1232 config TOUCHSCREEN_STMPE tristate "STMicroelectronics STMPE touchscreens" depends on MFD_STMPE + depends on (OF || COMPILE_TEST) help Say Y here if you want support for STMicroelectronics STMPE touchscreen controllers. diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index e4977c6250f3..e414d43e5159 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -267,27 +267,10 @@ static void stmpe_ts_close(struct input_dev *dev) static void stmpe_ts_get_platform_info(struct platform_device *pdev, struct stmpe_touch *ts) { - struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; - struct stmpe_ts_platform_data *ts_pdata = NULL; - - ts->stmpe = stmpe; - - if (stmpe->pdata && stmpe->pdata->ts) { - ts_pdata = stmpe->pdata->ts; - - ts->sample_time = ts_pdata->sample_time; - ts->mod_12b = ts_pdata->mod_12b; - ts->ref_sel = ts_pdata->ref_sel; - ts->adc_freq = ts_pdata->adc_freq; - ts->ave_ctrl = ts_pdata->ave_ctrl; - ts->touch_det_delay = ts_pdata->touch_det_delay; - ts->settling = ts_pdata->settling; - ts->fraction_z = ts_pdata->fraction_z; - ts->i_drive = ts_pdata->i_drive; - } else if (np) { - u32 val; + u32 val; + if (np) { if (!of_property_read_u32(np, "st,sample-time", &val)) ts->sample_time = val; if (!of_property_read_u32(np, "st,mod-12b", &val)) @@ -311,6 +294,7 @@ static void stmpe_ts_get_platform_info(struct platform_device *pdev, static int stmpe_input_probe(struct platform_device *pdev) { + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct stmpe_touch *ts; struct input_dev *idev; int error; @@ -329,6 +313,7 @@ static int stmpe_input_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, ts); + ts->stmpe = stmpe; ts->idev = idev; ts->dev = &pdev->dev; @@ -351,14 +336,13 @@ static int stmpe_input_probe(struct platform_device *pdev) idev->name = STMPE_TS_NAME; idev->phys = STMPE_TS_NAME"/input0"; idev->id.bustype = BUS_I2C; - idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); idev->open = stmpe_ts_open; idev->close = stmpe_ts_close; input_set_drvdata(idev, ts); + input_set_capability(idev, EV_KEY, BTN_TOUCH); input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0); input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); @@ -390,15 +374,12 @@ static struct platform_driver stmpe_ts_driver = { }; module_platform_driver(stmpe_ts_driver); -#ifdef CONFIG_OF static const struct of_device_id stmpe_ts_ids[] = { { .compatible = "st,stmpe-ts", }, { }, }; MODULE_DEVICE_TABLE(of, stmpe_ts_ids); -#endif MODULE_AUTHOR("Luotao Fu "); MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" STMPE_TS_NAME); diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h index c9d869027300..cb83883918a7 100644 --- a/include/linux/mfd/stmpe.h +++ b/include/linux/mfd/stmpe.h @@ -117,47 +117,6 @@ extern int stmpe_disable(struct stmpe *stmpe, unsigned int blocks); #define STMPE_GPIO_NOREQ_811_TOUCH (0xf0) -/** - * struct stmpe_ts_platform_data - stmpe811 touch screen controller platform - * data - * @sample_time: ADC converstion time in number of clock. - * (0 -> 36 clocks, 1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks, - * 4 -> 80 clocks, 5 -> 96 clocks, 6 -> 144 clocks), - * recommended is 4. - * @mod_12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC) - * @ref_sel: ADC reference source - * (0 -> internal reference, 1 -> external reference) - * @adc_freq: ADC Clock speed - * (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz) - * @ave_ctrl: Sample average control - * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples) - * @touch_det_delay: Touch detect interrupt delay - * (0 -> 10 us, 1 -> 50 us, 2 -> 100 us, 3 -> 500 us, - * 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms) - * recommended is 3 - * @settling: Panel driver settling time - * (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 -> 1 ms, - * 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms) - * recommended is 2 - * @fraction_z: Length of the fractional part in z - * (fraction_z ([0..7]) = Count of the fractional part) - * recommended is 7 - * @i_drive: current limit value of the touchscreen drivers - * (0 -> 20 mA typical 35 mA max, 1 -> 50 mA typical 80 mA max) - * - * */ -struct stmpe_ts_platform_data { - u8 sample_time; - u8 mod_12b; - u8 ref_sel; - u8 adc_freq; - u8 ave_ctrl; - u8 touch_det_delay; - u8 settling; - u8 fraction_z; - u8 i_drive; -}; - /** * struct stmpe_platform_data - STMPE platform data * @id: device id to distinguish between multiple STMPEs on the same board @@ -168,7 +127,6 @@ struct stmpe_ts_platform_data { * @irq_over_gpio: true if gpio is used to get irq * @irq_gpio: gpio number over which irq will be requested (significant only if * irq_over_gpio is true) - * @ts: touchscreen-specific platform data */ struct stmpe_platform_data { int id; @@ -178,8 +136,6 @@ struct stmpe_platform_data { bool irq_over_gpio; int irq_gpio; int autosleep_timeout; - - struct stmpe_ts_platform_data *ts; }; #endif -- cgit v1.2.3 From 7debcbb135f9d0e74596039d648f1ff2d87a9305 Mon Sep 17 00:00:00 2001 From: Shailendra Verma Date: Tue, 26 May 2015 13:44:06 -0700 Subject: Input: cyapa - fix a few typos in comments Signed-off-by: Shailendra Verma Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/cyapa_gen5.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 5b611dd71e79..afc39e799da2 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -352,7 +352,7 @@ struct gen5_app_cmd_head { u8 parameter_data[0]; /* Parameter data variable based on cmd_code */ } __packed; -/* Applicaton get/set parameter command data structure */ +/* Application get/set parameter command data structure */ struct gen5_app_set_parameter_data { u8 parameter_id; u8 parameter_size; @@ -832,7 +832,7 @@ static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data) int ret; /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header; - * 0x20 0x00 0xFF is Gen5 Booloader HID Description Header. + * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header. * * Must read HID Description content through out, * otherwise Gen5 trackpad cannot response next command @@ -1654,8 +1654,8 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, * that trackpad unable to report signal to wake system up * in the special situation that system is in suspending, and * at the same time, user touch trackpad to wake system up. - * This function can avoid the data to be buffured when system - * is suspending which may cause interrput line unable to be + * This function can avoid the data to be buffered when system + * is suspending which may cause interrupt line unable to be * asserted again. */ cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); @@ -2546,16 +2546,11 @@ static bool cyapa_gen5_irq_cmd_handler(struct cyapa *cyapa) gen5_pip->resp_sort_func(cyapa, gen5_pip->irq_cmd_buf, length))) { /* - * Cover the Gen5 V1 firmware issue. - * The issue is there is no interrut will be - * asserted to notityf host to read a command - * data out when always has finger touch on - * trackpad during the command is issued to - * trackad device. - * This issue has the scenario is that, - * user always has his fingers touched on - * trackpad device when booting/rebooting - * their chrome book. + * Work around the Gen5 V1 firmware + * that does not assert interrupt signalling + * that command response is ready if user + * keeps touching the trackpad while command + * is sent to the device. */ length = 0; if (gen5_pip->resp_len) -- cgit v1.2.3 From feb9eba80cce00c73a79ba22a5962657afadc476 Mon Sep 17 00:00:00 2001 From: Shailendra Verma Date: Tue, 26 May 2015 14:07:12 -0700 Subject: Input: psmouse - use true instead of 1 for boolean values The variable psmouse_smartscroll is bool type so assigning true instead of 1. Signed-off-by: Shailendra Verma Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 5bb1658f60c7..7c4ba43d253e 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -63,7 +63,7 @@ static unsigned int psmouse_rate = 100; module_param_named(rate, psmouse_rate, uint, 0644); MODULE_PARM_DESC(rate, "Report rate, in reports per second."); -static bool psmouse_smartscroll = 1; +static bool psmouse_smartscroll = true; module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); -- cgit v1.2.3 From e002273b37821941623d231b5c7346778b486c9b Mon Sep 17 00:00:00 2001 From: Shailendra Verma Date: Tue, 26 May 2015 14:08:37 -0700 Subject: Input: synaptics_i2c - use proper boolean values The variable no_decel is bool type so assigning "true" instead of "1". Also, synaptics_i2c_get_input() has bool return type, so let's use "false" there. Signed-off-by: Shailendra Verma Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics_i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 878f18498f3b..ffceedcaf3c8 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -185,7 +185,7 @@ #define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) /* Control touchpad's No Deceleration option */ -static bool no_decel = 1; +static bool no_decel = true; module_param(no_decel, bool, 0644); MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)"); @@ -340,9 +340,9 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) s32 data; s8 x_delta, y_delta; - /* Deal with spontanious resets and errors */ + /* Deal with spontaneous resets and errors */ if (synaptics_i2c_check_error(touch->client)) - return 0; + return false; /* Get Gesture Bit */ data = synaptics_i2c_reg_get(touch->client, DATA_REG0); -- cgit v1.2.3 From ffb6e0c9a0572f8e5f8e9337a1b40ac2ec1493a1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 May 2015 14:45:29 -0700 Subject: tty: remove platform_sysrq_reset_seq The platform_sysrq_reset_seq code was intended as a way for an embedded platform to provide its own sysrq sequence at compile time. After over two years, nobody has started using it in an upstream kernel, and the platforms that were interested in it have moved on to devicetree, which can be used to configure the sequence without requiring kernel changes. The method is also incompatible with the way that most architectures build support for multiple platforms into a single kernel. Now the code is producing warnings when built with gcc-5.1: drivers/tty/sysrq.c: In function 'sysrq_init': drivers/tty/sysrq.c:959:33: warning: array subscript is above array bounds [-Warray-bounds] key = platform_sysrq_reset_seq[i]; We could fix this, but it seems unlikely that it will ever be used, so let's just remove the code instead. We still have the option to pass the sequence either in DT, using the kernel command line, or using the /sys/module/sysrq/parameters/reset_seq file. Fixes: 154b7a489a ("Input: sysrq - allow specifying alternate reset sequence") Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/tty/sysrq.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 259a4d5a4e8f..b21881e39d28 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -55,9 +55,6 @@ static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static bool __read_mostly sysrq_always_enabled; -unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; -int sysrq_reset_downtime_ms __weak; - static bool sysrq_on(void) { return sysrq_enabled || sysrq_always_enabled; @@ -568,6 +565,7 @@ void handle_sysrq(int key) EXPORT_SYMBOL(handle_sysrq); #ifdef CONFIG_INPUT +static int sysrq_reset_downtime_ms; /* Simple translation table for the SysRq keys */ static const unsigned char sysrq_xlate[KEY_CNT] = @@ -948,23 +946,8 @@ static bool sysrq_handler_registered; static inline void sysrq_register_handler(void) { - unsigned short key; int error; - int i; - - /* First check if a __weak interface was instantiated. */ - for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) { - key = platform_sysrq_reset_seq[i]; - if (key == KEY_RESERVED || key > KEY_MAX) - break; - - sysrq_reset_seq[sysrq_reset_seq_len++] = key; - } - /* - * DT configuration takes precedence over anything that would - * have been defined via the __weak interface. - */ sysrq_of_get_keyreset_config(); error = input_register_handler(&sysrq_handler); -- cgit v1.2.3 From 85919a00e55f90e72405e707eb23c930b8d8db91 Mon Sep 17 00:00:00 2001 From: Dmitry Tunin Date: Sun, 31 May 2015 11:26:49 -0700 Subject: Input: focaltech - report finger width to userspace Focaltech touchpads report finger width in packet[5] of absolute packet. Range for width in raw format is 0x10 - 0x70. Second half-byte is always 0. 0xff is reported, when a large contact area is detected. This can be handled in userspace. Signed-off-by: Dmitry Tunin Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/focaltech.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index 23d259416f2f..4d5576de81be 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c @@ -103,6 +103,16 @@ struct focaltech_hw_state { */ struct focaltech_finger_state fingers[FOC_MAX_FINGERS]; + /* + * Finger width 0-7 and 15 for a very big contact area. + * 15 value stays until the finger is released. + * Width is reported only in absolute packets. + * Since hardware reports width only for last touching finger, + * there is no need to store width for every specific finger, + * so we keep only last value reported. + */ + unsigned int width; + /* True if the clickpad has been pressed. */ bool pressed; }; @@ -137,6 +147,7 @@ static void focaltech_report_state(struct psmouse *psmouse) input_report_abs(dev, ABS_MT_POSITION_X, clamped_x); input_report_abs(dev, ABS_MT_POSITION_Y, priv->y_max - clamped_y); + input_report_abs(dev, ABS_TOOL_WIDTH, state->width); } } input_mt_report_pointer_emulation(dev, true); @@ -187,6 +198,7 @@ static void focaltech_process_abs_packet(struct psmouse *psmouse, state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2]; state->fingers[finger].y = (packet[3] << 8) | packet[4]; + state->width = packet[5] >> 4; state->fingers[finger].valid = true; } @@ -331,6 +343,7 @@ static void focaltech_set_input_params(struct psmouse *psmouse) __set_bit(EV_ABS, dev->evbit); input_set_abs_params(dev, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); + input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0); input_mt_init_slots(dev, 5, INPUT_MT_POINTER); __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); } -- cgit v1.2.3 From 12018ac3d679d6a3c6c738ac805797fe4dd43912 Mon Sep 17 00:00:00 2001 From: Duson Lin Date: Mon, 8 Jun 2015 16:39:35 -0700 Subject: Input: elan_i2c - add support for multi IC type and iap format In order to support multiple IC types for i2c/smbus protocol, add get ic type command and use this data when checking firmware page count and signature address. Signed-off-by: Duson Lin Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 5 ++-- drivers/input/mouse/elan_i2c_core.c | 45 ++++++++++++++++++++++++++++++++---- drivers/input/mouse/elan_i2c_i2c.c | 4 +++- drivers/input/mouse/elan_i2c_smbus.c | 6 +++-- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 6d5f8a4c1748..ff622a1b0c2c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -33,9 +33,7 @@ #define ETP_FW_IAP_PAGE_ERR (1 << 5) #define ETP_FW_IAP_INTF_ERR (1 << 4) #define ETP_FW_PAGE_SIZE 64 -#define ETP_FW_VAILDPAGE_COUNT 768 #define ETP_FW_SIGNATURE_SIZE 6 -#define ETP_FW_SIGNATURE_ADDRESS 0xBFFA struct i2c_client; struct completion; @@ -58,7 +56,8 @@ struct elan_transport_ops { bool max_baseliune, u8 *value); int (*get_version)(struct i2c_client *client, bool iap, u8 *version); - int (*get_sm_version)(struct i2c_client *client, u8 *version); + int (*get_sm_version)(struct i2c_client *client, + u8* ic_type, u8 *version); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_product_id)(struct i2c_client *client, u8 *id); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index fd5068b2542d..b4cfd18cdaca 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -4,7 +4,7 @@ * Copyright (c) 2013 ELAN Microelectronics Corp. * * Author: 林政維 (Duson Lin) - * Version: 1.5.7 + * Version: 1.5.8 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -40,7 +40,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.5.7" +#define ELAN_DRIVER_VERSION "1.5.8" #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 #define ETP_FINGER_WIDTH 15 @@ -83,6 +83,9 @@ struct elan_tp_data { u16 fw_checksum; int pressure_adjustment; u8 mode; + u8 ic_type; + u16 fw_vaildpage_count; + u16 fw_signature_address; bool irq_wake; @@ -91,6 +94,29 @@ struct elan_tp_data { bool baseline_ready; }; +static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count, + u16 *signature_address) +{ + switch(ic_type) { + case 0x09: + *vaildpage_count = 768; + break; + case 0x0D: + *vaildpage_count = 896; + break; + default: + /* unknown ic type clear value */ + *vaildpage_count = 0; + *signature_address = 0; + return -ENXIO; + } + + *signature_address = + (*vaildpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; + + return 0; +} + static int elan_enable_power(struct elan_tp_data *data) { int repeat = ETP_RETRY_COUNT; @@ -221,7 +247,8 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; - error = data->ops->get_sm_version(data->client, &data->sm_version); + error = data->ops->get_sm_version(data->client, &data->ic_type, + &data->sm_version); if (error) return error; @@ -234,6 +261,14 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; + error = elan_get_fwinfo(data->ic_type, &data->fw_vaildpage_count, + &data->fw_signature_address); + if (error) { + dev_err(&data->client->dev, + "unknown ic type %d\n", data->ic_type); + return error; + } + return 0; } @@ -318,7 +353,7 @@ static int __elan_update_firmware(struct elan_tp_data *data, iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]); boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE; - for (i = boot_page_count; i < ETP_FW_VAILDPAGE_COUNT; i++) { + for (i = boot_page_count; i < data->fw_vaildpage_count; i++) { u16 checksum = 0; const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE]; @@ -454,7 +489,7 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, } /* Firmware file must match signature data */ - fw_signature = &fw->data[ETP_FW_SIGNATURE_ADDRESS]; + fw_signature = &fw->data[data->fw_signature_address]; if (memcmp(fw_signature, signature, sizeof(signature)) != 0) { dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n", (int)sizeof(signature), signature, diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index a0acbbf83bfd..683c840c9dd7 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -259,7 +259,8 @@ static int elan_i2c_get_version(struct i2c_client *client, return 0; } -static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version) +static int elan_i2c_get_sm_version(struct i2c_client *client, + u8 *ic_type, u8 *version) { int error; u8 val[3]; @@ -271,6 +272,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version) } *version = val[0]; + *ic_type = val[1]; return 0; } diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 30ab80dbcdd6..ff36a366b2aa 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -165,7 +165,8 @@ static int elan_smbus_get_version(struct i2c_client *client, return 0; } -static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version) +static int elan_smbus_get_sm_version(struct i2c_client *client, + u8 *ic_type, u8 *version) { int error; u8 val[3]; @@ -177,7 +178,8 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version) return error; } - *version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */ + *version = val[0]; + *ic_type = val[1]; return 0; } -- cgit v1.2.3 From 7b9f1830745cb3ad9e0f3774e83900610cedd39c Mon Sep 17 00:00:00 2001 From: Charlie Mooney Date: Mon, 8 Jun 2015 16:48:23 -0700 Subject: Input: elan_i2c - add product IDs FW names Previously the elan_i2c touchpad driver would simply request the firmware "/lib/firmware/elan_i2c.bin", which does not work well if there are multiple such devices in the system. Let's append the "product ID" (by using the same function as the sysfs interface for consistency) to the filename. This results in filenames of the form "/lib/firmware/elan_i2c_72.0.bin", allowing you to support multiple elan_i2c touchpads on the same device by simply naming each device's FW with its corresponding product ID. This way when you trigger a fw update the driver will load the correct binary. Signed-off-by: Charlie Mooney Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/elan_i2c.h | 3 ++- drivers/input/mouse/elan_i2c_core.c | 22 ++++++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index ff622a1b0c2c..73670f2aebfd 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -28,7 +28,8 @@ #define ETP_PRESSURE_OFFSET 25 /* IAP Firmware handling */ -#define ETP_FW_NAME "elan_i2c.bin" +#define ETP_PRODUCT_ID_FORMAT_STRING "%d.0" +#define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin" #define ETP_IAP_START_ADDR 0x0083 #define ETP_FW_IAP_PAGE_ERR (1 << 5) #define ETP_FW_IAP_INTF_ERR (1 << 4) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index b4cfd18cdaca..62641f2adaf7 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -4,7 +4,7 @@ * Copyright (c) 2013 ELAN Microelectronics Corp. * * Author: 林政維 (Duson Lin) - * Version: 1.5.8 + * Version: 1.5.9 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -40,7 +40,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.5.8" +#define ELAN_DRIVER_VERSION "1.5.9" #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 #define ETP_FINGER_WIDTH 15 @@ -438,7 +438,8 @@ static ssize_t elan_sysfs_read_product_id(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct elan_tp_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d.0\n", data->product_id); + return sprintf(buf, ETP_PRODUCT_ID_FORMAT_STRING "\n", + data->product_id); } static ssize_t elan_sysfs_read_fw_ver(struct device *dev, @@ -477,14 +478,23 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, { struct elan_tp_data *data = dev_get_drvdata(dev); const struct firmware *fw; + char *fw_name; int error; const u8 *fw_signature; static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF}; - error = request_firmware(&fw, ETP_FW_NAME, dev); + /* Look for a firmware with the product id appended. */ + fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id); + if (!fw_name) { + dev_err(dev, "failed to allocate memory for firmware name\n"); + return -ENOMEM; + } + + dev_info(dev, "requesting fw '%s'\n", fw_name); + error = request_firmware(&fw, fw_name, dev); + kfree(fw_name); if (error) { - dev_err(dev, "cannot load firmware %s: %d\n", - ETP_FW_NAME, error); + dev_err(dev, "failed to request firmware: %d\n", error); return error; } -- cgit v1.2.3 From 5179f0ce2f96f155e3bda93b3b82f912dbaddad2 Mon Sep 17 00:00:00 2001 From: Steve Twiss Date: Mon, 8 Jun 2015 16:26:20 -0700 Subject: Input: add OnKey driver for DA9063 MFD part This adds OnKey driver support for DA9063. Signed-off-by: Steve Twiss Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 10 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/da9063_onkey.c | 226 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/da9063/pdata.h | 1 + 4 files changed, 238 insertions(+) create mode 100644 drivers/input/misc/da9063_onkey.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index e5c4de279001..d4f0a817e858 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -610,6 +610,16 @@ config INPUT_DA9055_ONKEY To compile this driver as a module, choose M here: the module will be called da9055_onkey. +config INPUT_DA9063_ONKEY + tristate "Dialog DA9063 OnKey" + depends on MFD_DA9063 + help + Support the ONKEY of Dialog DA9063 Power Management IC as an + input device reporting power button statue. + + To compile this driver as a module, choose M here: the module + will be called da9063_onkey. + config INPUT_DM355EVM tristate "TI DaVinci DM355 EVM Keypad and IR Remote" depends on MFD_DM355EVM_MSP diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index d3179472474d..53df07dcc23c 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o +obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_E3X0_BUTTON) += e3x0-button.o obj-$(CONFIG_INPUT_DRV260X_HAPTICS) += drv260x.o diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c new file mode 100644 index 000000000000..f577585ef999 --- /dev/null +++ b/drivers/input/misc/da9063_onkey.c @@ -0,0 +1,226 @@ +/* + * OnKey device driver for DA9063 + * Copyright (C) 2015 Dialog Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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 +#include +#include +#include +#include + +struct da9063_onkey { + struct da9063 *hw; + struct delayed_work work; + struct input_dev *input; + struct device *dev; + bool key_power; +}; + +static void da9063_poll_on(struct work_struct *work) +{ + struct da9063_onkey *onkey = container_of(work, struct da9063_onkey, + work.work); + unsigned int val; + int fault_log = 0; + bool poll = true; + int error; + + /* Poll to see when the pin is released */ + error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); + if (error) { + dev_err(onkey->dev, + "Failed to read ON status: %d\n", error); + goto err_poll; + } + + if (!(val & DA9063_NONKEY)) { + error = regmap_update_bits(onkey->hw->regmap, + DA9063_REG_CONTROL_B, + DA9063_NONKEY_LOCK, 0); + if (error) { + dev_err(onkey->dev, + "Failed to reset the Key Delay %d\n", error); + goto err_poll; + } + + input_report_key(onkey->input, KEY_POWER, 0); + input_sync(onkey->input); + + poll = false; + } + + /* + * If the fault log KEY_RESET is detected, then clear it + * and shut down the system. + */ + error = regmap_read(onkey->hw->regmap, + DA9063_REG_FAULT_LOG, &fault_log); + if (error) { + dev_warn(&onkey->input->dev, + "Cannot read FAULT_LOG: %d\n", error); + } else if (fault_log & DA9063_KEY_RESET) { + error = regmap_write(onkey->hw->regmap, + DA9063_REG_FAULT_LOG, + DA9063_KEY_RESET); + if (error) { + dev_warn(&onkey->input->dev, + "Cannot reset KEY_RESET fault log: %d\n", + error); + } else { + /* at this point we do any S/W housekeeping + * and then send shutdown command + */ + dev_dbg(&onkey->input->dev, + "Sending SHUTDOWN to DA9063 ...\n"); + error = regmap_write(onkey->hw->regmap, + DA9063_REG_CONTROL_F, + DA9063_SHUTDOWN); + if (error) + dev_err(&onkey->input->dev, + "Cannot SHUTDOWN DA9063: %d\n", + error); + } + } + +err_poll: + if (poll) + schedule_delayed_work(&onkey->work, msecs_to_jiffies(50)); +} + +static irqreturn_t da9063_onkey_irq_handler(int irq, void *data) +{ + struct da9063_onkey *onkey = data; + unsigned int val; + int error; + + error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val); + if (onkey->key_power && !error && (val & DA9063_NONKEY)) { + input_report_key(onkey->input, KEY_POWER, 1); + input_sync(onkey->input); + schedule_delayed_work(&onkey->work, 0); + dev_dbg(onkey->dev, "KEY_POWER pressed.\n"); + } else { + input_report_key(onkey->input, KEY_SLEEP, 1); + input_sync(onkey->input); + input_report_key(onkey->input, KEY_SLEEP, 0); + input_sync(onkey->input); + dev_dbg(onkey->dev, "KEY_SLEEP pressed.\n"); + } + + return IRQ_HANDLED; +} + +static void da9063_cancel_poll(void *data) +{ + struct da9063_onkey *onkey = data; + + cancel_delayed_work_sync(&onkey->work); +} + +static int da9063_onkey_probe(struct platform_device *pdev) +{ + struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent); + struct da9063_pdata *pdata = dev_get_platdata(da9063->dev); + struct da9063_onkey *onkey; + int irq; + int error; + + onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey), + GFP_KERNEL); + if (!onkey) { + dev_err(&pdev->dev, "Failed to allocate memory.\n"); + return -ENOMEM; + } + + onkey->dev = &pdev->dev; + onkey->hw = da9063; + + if (pdata) + onkey->key_power = pdata->key_power; + else + onkey->key_power = + !of_property_read_bool(pdev->dev.of_node, + "dlg,disable-key-power"); + + onkey->input = devm_input_allocate_device(&pdev->dev); + if (!onkey->input) { + dev_err(&pdev->dev, "Failed to allocated input device.\n"); + return -ENOMEM; + } + + onkey->input->name = DA9063_DRVNAME_ONKEY; + onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0"; + onkey->input->dev.parent = &pdev->dev; + + if (onkey->key_power) + input_set_capability(onkey->input, EV_KEY, KEY_POWER); + + input_set_capability(onkey->input, EV_KEY, KEY_SLEEP); + + INIT_DELAYED_WORK(&onkey->work, da9063_poll_on); + + error = devm_add_action(&pdev->dev, da9063_cancel_poll, onkey); + if (error) { + dev_err(&pdev->dev, + "Failed to add cancel poll action: %d\n", + error); + return error; + } + + irq = platform_get_irq_byname(pdev, "ONKEY"); + if (irq < 0) { + error = irq; + dev_err(&pdev->dev, "Failed to get platform IRQ: %d\n", error); + return error; + } + + error = devm_request_threaded_irq(&pdev->dev, irq, + NULL, da9063_onkey_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "ONKEY", onkey); + if (error) { + dev_err(&pdev->dev, + "Failed to request IRQ %d: %d\n", irq, error); + return error; + } + + error = input_register_device(onkey->input); + if (error) { + dev_err(&pdev->dev, + "Failed to register input device: %d\n", error); + return error; + } + + platform_set_drvdata(pdev, onkey); + return 0; +} + +static struct platform_driver da9063_onkey_driver = { + .probe = da9063_onkey_probe, + .driver = { + .name = DA9063_DRVNAME_ONKEY, + }, +}; +module_platform_driver(da9063_onkey_driver); + +MODULE_AUTHOR("S Twiss "); +MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY); diff --git a/include/linux/mfd/da9063/pdata.h b/include/linux/mfd/da9063/pdata.h index 95c8742215a7..612383bd80ae 100644 --- a/include/linux/mfd/da9063/pdata.h +++ b/include/linux/mfd/da9063/pdata.h @@ -103,6 +103,7 @@ struct da9063; struct da9063_pdata { int (*init)(struct da9063 *da9063); int irq_base; + bool key_power; unsigned flags; struct da9063_regulators_pdata *regulators_pdata; struct led_platform_data *leds_pdata; -- cgit v1.2.3 From 0dfb35bd39d16ca2b69d5ddaa76a143c814eca45 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 9 Jun 2015 11:01:38 -0700 Subject: Input: goodix - fix alignment issues Fix alignment to match open parenthesis detected by running checkpatch.pl --strict. Signed-off-by: Irina Tirdea Acked-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 0d93b1e5e28e..099fc466bd16 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -69,7 +69,7 @@ static const unsigned long goodix_irq_flags[] = { * @len: length of the buffer to write */ static int goodix_i2c_read(struct i2c_client *client, - u16 reg, u8 *buf, int len) + u16 reg, u8 *buf, int len) { struct i2c_msg msgs[2]; u16 wbuf = cpu_to_be16(reg); @@ -78,7 +78,7 @@ static int goodix_i2c_read(struct i2c_client *client, msgs[0].flags = 0; msgs[0].addr = client->addr; msgs[0].len = 2; - msgs[0].buf = (u8 *) &wbuf; + msgs[0].buf = (u8 *)&wbuf; msgs[1].flags = I2C_M_RD; msgs[1].addr = client->addr; @@ -199,8 +199,8 @@ static void goodix_read_config(struct goodix_ts_data *ts) int error; error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA, - config, - GOODIX_CONFIG_MAX_LENGTH); + config, + GOODIX_CONFIG_MAX_LENGTH); if (error) { dev_warn(&ts->client->dev, "Error reading config (%d), using defaults\n", @@ -296,10 +296,10 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, - ts->abs_x_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, - ts->abs_y_max, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, + 0, ts->abs_x_max, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, + 0, ts->abs_y_max, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); -- cgit v1.2.3 From 0e0432f04ee5d73b45faefc7bbb63b75fcaefa42 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 9 Jun 2015 11:03:15 -0700 Subject: Input: goodix - fix variable length array warning Fix sparse warning: drivers/input/touchscreen/goodix.c:182:26: warning: Variable length array is used. Replace the variable length array with fixed length. Some Goodix devices have maximum 5 touch points, while others have 10 touch points. Using the maximum length (80 bytes) for all devices will lead to wasting 40 bytes on stack when using devices with maximum 5 touch points. However, that is preferable to using kmalloc which will use even more resources. Signed-off-by: Irina Tirdea Acked-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 099fc466bd16..6457033439d5 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -147,7 +147,7 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) */ static void goodix_process_events(struct goodix_ts_data *ts) { - u8 point_data[1 + GOODIX_CONTACT_SIZE * ts->max_touch_num]; + u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; int touch_num; int i; -- cgit v1.2.3 From e70b03071c5d43ea7a63b007a1c4bf285a2772d1 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 9 Jun 2015 11:04:40 -0700 Subject: Input: goodix - export id and version read from device Goodix touchscreens export through their registers a Product ID and Firmware Version. The Product ID is an ASCII encoding of the product name (e.g.: "911"). Export to sysfs (through the input subsystem) the product id and firmware version read from the device rather than using constant values. Signed-off-by: Octavian Purdila Signed-off-by: Irina Tirdea Acked-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 6457033439d5..73ade35ea90f 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -47,7 +47,7 @@ struct goodix_ts_data { /* Register defines */ #define GOODIX_READ_COOR_ADDR 0x814E #define GOODIX_REG_CONFIG_DATA 0x8047 -#define GOODIX_REG_VERSION 0x8140 +#define GOODIX_REG_ID 0x8140 #define RESOLUTION_LOC 1 #define MAX_CONTACTS_LOC 5 @@ -230,22 +230,28 @@ static void goodix_read_config(struct goodix_ts_data *ts) * * @client: the i2c client * @version: output buffer containing the version on success + * @id: output buffer containing the id on success */ -static int goodix_read_version(struct i2c_client *client, u16 *version) +static int goodix_read_version(struct i2c_client *client, u16 *version, u16 *id) { int error; u8 buf[6]; + char id_str[5]; - error = goodix_i2c_read(client, GOODIX_REG_VERSION, buf, sizeof(buf)); + error = goodix_i2c_read(client, GOODIX_REG_ID, buf, sizeof(buf)); if (error) { dev_err(&client->dev, "read version failed: %d\n", error); return error; } - if (version) - *version = get_unaligned_le16(&buf[4]); + memcpy(id_str, buf, 4); + id_str[4] = 0; + if (kstrtou16(id_str, 10, id)) + *id = 0x1001; - dev_info(&client->dev, "IC VERSION: %6ph\n", buf); + *version = get_unaligned_le16(&buf[4]); + + dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version); return 0; } @@ -279,10 +285,13 @@ static int goodix_i2c_test(struct i2c_client *client) * goodix_request_input_dev - Allocate, populate and register the input device * * @ts: our goodix_ts_data pointer + * @version: device firmware version + * @id: device ID * * Must be called during probe */ -static int goodix_request_input_dev(struct goodix_ts_data *ts) +static int goodix_request_input_dev(struct goodix_ts_data *ts, u16 version, + u16 id) { int error; @@ -310,8 +319,8 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) ts->input_dev->phys = "input/ts"; ts->input_dev->id.bustype = BUS_I2C; ts->input_dev->id.vendor = 0x0416; - ts->input_dev->id.product = 0x1001; - ts->input_dev->id.version = 10427; + ts->input_dev->id.product = id; + ts->input_dev->id.version = version; error = input_register_device(ts->input_dev); if (error) { @@ -329,7 +338,7 @@ static int goodix_ts_probe(struct i2c_client *client, struct goodix_ts_data *ts; unsigned long irq_flags; int error; - u16 version_info; + u16 version_info, id_info; dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr); @@ -351,7 +360,7 @@ static int goodix_ts_probe(struct i2c_client *client, return error; } - error = goodix_read_version(client, &version_info); + error = goodix_read_version(client, &version_info, &id_info); if (error) { dev_err(&client->dev, "Read version failed.\n"); return error; @@ -359,7 +368,7 @@ static int goodix_ts_probe(struct i2c_client *client, goodix_read_config(ts); - error = goodix_request_input_dev(ts); + error = goodix_request_input_dev(ts, version_info, id_info); if (error) return error; -- cgit v1.2.3 From c7a4fb53de365d5e9264e3fa5bdb9c0a52b6f9a0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 9 Jun 2015 11:51:05 -0700 Subject: Input: goodix - do not explicitly set evbits in input device input_mt_init_slots() will do that for us. Reviewed-by: Benjamin Tissoires Acked-by: Bastien Nocera Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/goodix.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 73ade35ea90f..b4d12e29abff 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -301,10 +301,6 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts, u16 version, return -ENOMEM; } - ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | - BIT_MASK(EV_KEY) | - BIT_MASK(EV_ABS); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, -- cgit v1.2.3 From cf99289d67688c4f92175da42bd1647695f6fddc Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Thu, 11 Jun 2015 13:07:59 -0700 Subject: Input: cyttsp4 - use swap() in cyttsp4_get_touch() Use kernel.h macro definition. Thanks to Julia Lawall for Coccinelle scripting support. Signed-off-by: Fabian Frederick Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp4_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index 568a3d340c8a..5ed31057430c 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -775,7 +775,6 @@ static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, struct device *dev = &md->input->dev; struct cyttsp4_sysinfo *si = md->si; enum cyttsp4_tch_abs abs; - int tmp; bool flipped; for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { @@ -790,9 +789,7 @@ static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, } if (md->pdata->flags & CY_FLAG_FLIP) { - tmp = touch->abs[CY_TCH_X]; - touch->abs[CY_TCH_X] = touch->abs[CY_TCH_Y]; - touch->abs[CY_TCH_Y] = tmp; + swap(touch->abs[CY_TCH_X], touch->abs[CY_TCH_Y]); flipped = true; } else flipped = false; -- cgit v1.2.3 From f60c8ba77dcea80af8facfd786a0d2c3ace86f3d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 16 Mar 2015 21:19:56 -0700 Subject: Input: export LEDs as class devices in sysfs This change creates a new input handler called "leds" that exports LEDs on input devices as standard LED class devices in sysfs and allows controlling their state via sysfs or via any of the standard LED triggers. This allows to re-purpose and reassign LDEs on the keyboards to represent states other than the standard keyboard states (CapsLock, NumLock, etc). The old API of controlling input LEDs by writing into /dev/input/eventX devices is still present and will take precedence over accessing via LEDs subsystem (i.e. it may override state set by a trigger). If input device is "grabbed" then requests coming through LED subsystem will be ignored. Signed-off-by: Samuel Thibault Tested-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- Documentation/leds/leds-class.txt | 3 - drivers/input/Kconfig | 13 +++ drivers/input/Makefile | 1 + drivers/input/input-leds.c | 212 ++++++++++++++++++++++++++++++++++++++ drivers/leds/Kconfig | 3 - 5 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 drivers/input/input-leds.c diff --git a/Documentation/leds/leds-class.txt b/Documentation/leds/leds-class.txt index 79699c200766..62261c04060a 100644 --- a/Documentation/leds/leds-class.txt +++ b/Documentation/leds/leds-class.txt @@ -2,9 +2,6 @@ LED handling under Linux ======================== -If you're reading this and thinking about keyboard leds, these are -handled by the input subsystem and the led class is *not* needed. - In its simplest form, the LED class just allows control of LEDs from userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the LED is defined in max_brightness file. The brightness file will set the brightness diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index a11ff74a5127..a35532ec00e4 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -25,6 +25,19 @@ config INPUT if INPUT +config INPUT_LEDS + tristate "Export input device LEDs in sysfs" + depends on LEDS_CLASS + default INPUT + help + Say Y here if you would like to export LEDs on input devices + as standard LED class devices in sysfs. + + If unsure, say Y. + + To compile this driver as a module, choose M here: the + module will be called input-leds. + config INPUT_FF_MEMLESS tristate "Support for memoryless force-feedback devices" help diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 5ca3f631497f..0c9302ca9954 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o +obj-$(CONFIG_INPUT_LEDS) += input-leds.o obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c new file mode 100644 index 000000000000..074a65ed17bb --- /dev/null +++ b/drivers/input/input-leds.c @@ -0,0 +1,212 @@ +/* + * LED support for the input layer + * + * Copyright 2010-2015 Samuel Thibault + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#if IS_ENABLED(CONFIG_VT) +#define VT_TRIGGER(_name) .trigger = _name +#else +#define VT_TRIGGER(_name) .trigger = NULL +#endif + +static const struct { + const char *name; + const char *trigger; +} input_led_info[LED_CNT] = { + [LED_NUML] = { "numlock", VT_TRIGGER("kbd-numlock") }, + [LED_CAPSL] = { "capslock", VT_TRIGGER("kbd-capslock") }, + [LED_SCROLLL] = { "scrolllock", VT_TRIGGER("kbd-scrolllock") }, + [LED_COMPOSE] = { "compose" }, + [LED_KANA] = { "kana", VT_TRIGGER("kbd-kanalock") }, + [LED_SLEEP] = { "sleep" } , + [LED_SUSPEND] = { "suspend" }, + [LED_MUTE] = { "mute" }, + [LED_MISC] = { "misc" }, + [LED_MAIL] = { "mail" }, + [LED_CHARGING] = { "charging" }, +}; + +struct input_led { + struct led_classdev cdev; + struct input_handle *handle; + unsigned int code; /* One of LED_* constants */ +}; + +struct input_leds { + struct input_handle handle; + unsigned int num_leds; + struct input_led leds[]; +}; + +static enum led_brightness input_leds_brightness_get(struct led_classdev *cdev) +{ + struct input_led *led = container_of(cdev, struct input_led, cdev); + struct input_dev *input = led->handle->dev; + + return test_bit(led->code, input->led) ? cdev->max_brightness : 0; +} + +static void input_leds_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct input_led *led = container_of(cdev, struct input_led, cdev); + + input_inject_event(led->handle, EV_LED, led->code, !!brightness); +} + +static void input_leds_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ +} + +static int input_leds_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_leds *leds; + unsigned int num_leds; + unsigned int led_code; + int led_no; + int error; + + num_leds = bitmap_weight(dev->ledbit, LED_CNT); + if (!num_leds) + return -ENXIO; + + leds = kzalloc(sizeof(*leds) + num_leds * sizeof(*leds->leds), + GFP_KERNEL); + if (!leds) + return -ENOMEM; + + leds->num_leds = num_leds; + + leds->handle.dev = dev; + leds->handle.handler = handler; + leds->handle.name = "leds"; + leds->handle.private = leds; + + error = input_register_handle(&leds->handle); + if (error) + goto err_free_mem; + + error = input_open_device(&leds->handle); + if (error) + goto err_unregister_handle; + + led_no = 0; + for_each_set_bit(led_code, dev->ledbit, LED_CNT) { + struct input_led *led = &leds->leds[led_no]; + + led->handle = &leds->handle; + led->code = led_code; + + if (WARN_ON(!input_led_info[led_code].name)) + continue; + + led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s", + dev_name(&dev->dev), + input_led_info[led_code].name); + if (!led->cdev.name) { + error = -ENOMEM; + goto err_unregister_leds; + } + + led->cdev.max_brightness = 1; + led->cdev.brightness_get = input_leds_brightness_get; + led->cdev.brightness_set = input_leds_brightness_set; + led->cdev.default_trigger = input_led_info[led_code].trigger; + + error = led_classdev_register(&dev->dev, &led->cdev); + if (error) { + dev_err(&dev->dev, "failed to register LED %s: %d\n", + led->cdev.name, error); + kfree(led->cdev.name); + goto err_unregister_leds; + } + + led_no++; + } + + return 0; + +err_unregister_leds: + while (--led_no >= 0) { + struct input_led *led = &leds->leds[led_no]; + + led_classdev_unregister(&led->cdev); + kfree(led->cdev.name); + } + + input_close_device(&leds->handle); + +err_unregister_handle: + input_unregister_handle(&leds->handle); + +err_free_mem: + kfree(leds); + return error; +} + +static void input_leds_disconnect(struct input_handle *handle) +{ + struct input_leds *leds = handle->private; + int i; + + for (i = 0; i < leds->num_leds; i++) { + struct input_led *led = &leds->leds[i]; + + led_classdev_unregister(&led->cdev); + kfree(led->cdev.name); + } + + input_close_device(handle); + input_unregister_handle(handle); + + kfree(leds); +} + +static const struct input_device_id input_leds_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_LED) }, + }, + { }, +}; +MODULE_DEVICE_TABLE(input, input_leds_ids); + +static struct input_handler input_leds_handler = { + .event = input_leds_event, + .connect = input_leds_connect, + .disconnect = input_leds_disconnect, + .name = "leds", + .id_table = input_leds_ids, +}; + +static int __init input_leds_init(void) +{ + return input_register_handler(&input_leds_handler); +} +module_init(input_leds_init); + +static void __exit input_leds_exit(void) +{ + input_unregister_handler(&input_leds_handler); +} +module_exit(input_leds_exit); + +MODULE_AUTHOR("Samuel Thibault "); +MODULE_AUTHOR("Dmitry Torokhov "); +MODULE_DESCRIPTION("Input -> LEDs Bridge"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 25b320d64e26..95029dfd311a 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -11,9 +11,6 @@ menuconfig NEW_LEDS Say Y to enable Linux LED support. This allows control of supported LEDs from both userspace and optionally, by kernel events (triggers). - This is not related to standard keyboard LEDs which are controlled - via the input system. - if NEW_LEDS config LEDS_CLASS -- cgit v1.2.3 From 5235552273e6b68abbed3b3047af6344e2e60c2c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 16 Mar 2015 21:19:44 -0700 Subject: tty/vt/keyboard: define LED triggers for VT LED states Now that input core allows controlling keyboards LEDs via standard LED subsystem triggers let's switch VT keyboard code to make use of this feature. We will define the following standard triggers: "kbd-scrollock", "kbd-numlock", "kbd-capslock", and "kbd-kanalock" which are default triggers for respective LEDs on keyboards. Signed-off-by: Samuel Thibault Tested-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/tty/vt/keyboard.c | 141 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 8a89f6e7715d..fc080bf1c4d2 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -961,6 +962,110 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) } } +#if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS) + +struct kbd_led_trigger { + struct led_trigger trigger; + unsigned int mask; +}; + +static void kbd_led_trigger_activate(struct led_classdev *cdev) +{ + struct kbd_led_trigger *trigger = + container_of(cdev->trigger, struct kbd_led_trigger, trigger); + + tasklet_disable(&keyboard_tasklet); + if (ledstate != 0xff) + led_trigger_event(&trigger->trigger, + ledstate & trigger->mask ? + LED_FULL : LED_OFF); + tasklet_enable(&keyboard_tasklet); +} + +#define KBD_LED_TRIGGER(_led_bit, _name) { \ + .trigger = { \ + .name = _name, \ + .activate = kbd_led_trigger_activate, \ + }, \ + .mask = BIT(_led_bit), \ + } + +static struct kbd_led_trigger kbd_led_triggers[] = { + KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), + KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), + KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), + KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), +}; + +static void kbd_propagate_led_state(unsigned int old_state, + unsigned int new_state) +{ + struct kbd_led_trigger *trigger; + unsigned int changed = old_state ^ new_state; + int i; + + for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) { + trigger = &kbd_led_triggers[i]; + + if (changed & trigger->mask) + led_trigger_event(&trigger->trigger, + new_state & trigger->mask ? + LED_FULL : LED_OFF); + } +} + +static int kbd_update_leds_helper(struct input_handle *handle, void *data) +{ + unsigned int led_state = *(unsigned int *)data; + + if (test_bit(EV_LED, handle->dev->evbit)) + kbd_propagate_led_state(~led_state, led_state); + + return 0; +} + +static void kbd_init_leds(void) +{ + int error; + int i; + + for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) { + error = led_trigger_register(&kbd_led_triggers[i].trigger); + if (error) + pr_err("error %d while registering trigger %s\n", + error, kbd_led_triggers[i].trigger.name); + } +} + +#else + +static int kbd_update_leds_helper(struct input_handle *handle, void *data) +{ + unsigned int leds = *(unsigned int *)data; + + if (test_bit(EV_LED, handle->dev->evbit)) { + input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); + input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_inject_event(handle, EV_SYN, SYN_REPORT, 0); + } + + return 0; +} + +static void kbd_propagate_led_state(unsigned int old_state, + unsigned int new_state) +{ + input_handler_for_each_handle(&kbd_handler, &new_state, + kbd_update_leds_helper); +} + +static void kbd_init_leds(void) +{ +} + +#endif + /* * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, * or (ii) whatever pattern of lights people want to show using KDSETLED, @@ -995,20 +1100,6 @@ static inline unsigned char getleds(void) return kb->ledflagstate; } -static int kbd_update_leds_helper(struct input_handle *handle, void *data) -{ - unsigned char leds = *(unsigned char *)data; - - if (test_bit(EV_LED, handle->dev->evbit)) { - input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); - input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_inject_event(handle, EV_SYN, SYN_REPORT, 0); - } - - return 0; -} - /** * vt_get_leds - helper for braille console * @console: console to read @@ -1085,24 +1176,22 @@ void vt_kbd_con_stop(int console) } /* - * This is the tasklet that updates LED state on all keyboards - * attached to the box. The reason we use tasklet is that we - * need to handle the scenario when keyboard handler is not - * registered yet but we already getting updates from the VT to - * update led state. + * This is the tasklet that updates LED state of LEDs using standard + * keyboard triggers. The reason we use tasklet is that we need to + * handle the scenario when keyboard handler is not registered yet + * but we already getting updates from the VT to update led state. */ static void kbd_bh(unsigned long dummy) { unsigned char leds; unsigned long flags; - + spin_lock_irqsave(&led_lock, flags); leds = getleds(); spin_unlock_irqrestore(&led_lock, flags); if (leds != ledstate) { - input_handler_for_each_handle(&kbd_handler, &leds, - kbd_update_leds_helper); + kbd_propagate_led_state(ledstate, leds); ledstate = leds; } } @@ -1450,8 +1539,10 @@ static void kbd_start(struct input_handle *handle) { tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) - kbd_update_leds_helper(handle, &ledstate); + if (ledstate != 0xff) { + unsigned int state = ledstate; + kbd_update_leds_helper(handle, &state); + } tasklet_enable(&keyboard_tasklet); } @@ -1497,6 +1588,8 @@ int __init kbd_init(void) kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; } + kbd_init_leds(); + error = input_register_handler(&kbd_handler); if (error) return error; -- cgit v1.2.3 From eeb64c14275e52740d6410632e62e0ad9b88ca70 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 6 Jun 2015 11:44:39 -0700 Subject: tty/vt/keyboard: define LED triggers for VT keyboard lock states In addition to defining triggers for VT LED states, let's define triggers for VT keyboard lock states, such as "kbd-shiftlock", "kbd-altgrlock", etc. This permits to fix #7063 from userland by using a modifier to implement proper CapsLock behavior and have the keyboard caps lock led show that modifier state. Signed-off-by: Samuel Thibault Tested-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/tty/vt/keyboard.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index fc080bf1c4d2..6f0336fff501 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -130,7 +130,7 @@ static char rep; /* flag telling character repeat */ static int shift_state = 0; -static unsigned char ledstate = 0xff; /* undefined */ +static unsigned int ledstate = -1U; /* undefined */ static unsigned char ledioctl; /* @@ -975,7 +975,7 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) container_of(cdev->trigger, struct kbd_led_trigger, trigger); tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) + if (ledstate != -1U) led_trigger_event(&trigger->trigger, ledstate & trigger->mask ? LED_FULL : LED_OFF); @@ -990,11 +990,23 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) .mask = BIT(_led_bit), \ } +#define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \ + KBD_LED_TRIGGER((_led_bit) + 8, _name) + static struct kbd_led_trigger kbd_led_triggers[] = { KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), + + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"), + KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"), + KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"), + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"), + KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"), }; static void kbd_propagate_led_state(unsigned int old_state, @@ -1073,7 +1085,7 @@ static void kbd_init_leds(void) */ static unsigned char getledstate(void) { - return ledstate; + return ledstate & 0xff; } void setledstate(struct kbd_struct *kb, unsigned int led) @@ -1183,11 +1195,12 @@ void vt_kbd_con_stop(int console) */ static void kbd_bh(unsigned long dummy) { - unsigned char leds; + unsigned int leds; unsigned long flags; spin_lock_irqsave(&led_lock, flags); leds = getleds(); + leds |= (unsigned int)kbd->lockstate << 8; spin_unlock_irqrestore(&led_lock, flags); if (leds != ledstate) { @@ -1539,10 +1552,8 @@ static void kbd_start(struct input_handle *handle) { tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) { - unsigned int state = ledstate; - kbd_update_leds_helper(handle, &state); - } + if (ledstate != -1U) + kbd_update_leds_helper(handle, &ledstate); tasklet_enable(&keyboard_tasklet); } -- cgit v1.2.3 From ea0afac450d2a3aaeb4c51ddf1631e677afe3193 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 16 Jun 2015 17:02:13 -0700 Subject: Input: improve usage of gpiod API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 39b2bbe3d715 (gpio: add flags argument to gpiod_get*() functions) which appeared in v3.17-rc1, the gpiod_get* functions take an additional parameter that allows to specify direction and initial value for output. Simplify drivers accordingly. Note that in the case of the drv260x driver error checking is more strict now because -ENOSYS is reported to the caller now. But this should only be returned if GPIOLIB is disabled which shouldn't happen as the driver depends on GPIOLIB. Signed-off-by: Uwe Kleine-König Reviewed-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/clps711x-keypad.c | 7 +------ drivers/input/misc/drv260x.c | 13 ++++--------- drivers/input/misc/gpio-beeper.c | 7 +------ 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index 27ef29f8fe6a..b637f1af842e 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -120,14 +120,9 @@ static int clps711x_keypad_probe(struct platform_device *pdev) for (i = 0; i < priv->row_count; i++) { struct clps711x_gpio_data *data = &priv->gpio_data[i]; - data->desc = devm_gpiod_get_index(dev, "row", i); - if (!data->desc) - return -EINVAL; - + data->desc = devm_gpiod_get_index(dev, "row", i, GPIOD_IN); if (IS_ERR(data->desc)) return PTR_ERR(data->desc); - - gpiod_direction_input(data->desc); } err = of_property_read_u32(np, "poll-interval", &poll_interval); diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 599578042ea0..e5d60ecd29a4 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -580,15 +580,10 @@ static int drv260x_probe(struct i2c_client *client, return error; } - haptics->enable_gpio = devm_gpiod_get(&client->dev, "enable"); - if (IS_ERR(haptics->enable_gpio)) { - error = PTR_ERR(haptics->enable_gpio); - if (error != -ENOENT && error != -ENOSYS) - return error; - haptics->enable_gpio = NULL; - } else { - gpiod_direction_output(haptics->enable_gpio, 1); - } + haptics->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(haptics->enable_gpio)) + return PTR_ERR(haptics->enable_gpio); haptics->input_dev = devm_input_allocate_device(&client->dev); if (!haptics->input_dev) { diff --git a/drivers/input/misc/gpio-beeper.c b/drivers/input/misc/gpio-beeper.c index 4817c5f0c3e4..16272fffeb7e 100644 --- a/drivers/input/misc/gpio-beeper.c +++ b/drivers/input/misc/gpio-beeper.c @@ -66,13 +66,12 @@ static int gpio_beeper_probe(struct platform_device *pdev) { struct gpio_beeper *beep; struct input_dev *input; - int err; beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); if (!beep) return -ENOMEM; - beep->desc = devm_gpiod_get(&pdev->dev, NULL); + beep->desc = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW); if (IS_ERR(beep->desc)) return PTR_ERR(beep->desc); @@ -92,10 +91,6 @@ static int gpio_beeper_probe(struct platform_device *pdev) input_set_capability(input, EV_SND, SND_BELL); - err = gpiod_direction_output(beep->desc, 0); - if (err) - return err; - input_set_drvdata(input, beep); return input_register_device(input); -- cgit v1.2.3 From 84c88ef9affb34f10cb5b66b07e2d496845d1c28 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 11 Jun 2015 17:54:13 -0700 Subject: MAINTAINERS: remove non existent input mt git tree The "INPUT MULTITOUCH (MT) PROTOCOL" entry git tree is not there on git.kernel.org. Signed-off-by: Baruch Siach Signed-off-by: Dmitry Torokhov --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 460ab22db181..fe3b839eac65 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5043,7 +5043,6 @@ F: include/linux/input/ INPUT MULTITOUCH (MT) PROTOCOL M: Henrik Rydberg L: linux-input@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt.git S: Odd fixes F: Documentation/input/multi-touch-protocol.txt F: drivers/input/input-mt.c -- cgit v1.2.3 From 469d7d22cea146e40efe8c330e5164b4d8f13934 Mon Sep 17 00:00:00 2001 From: Frodo Lai Date: Tue, 16 Jun 2015 15:03:53 -0700 Subject: Input: pixcir_i2c_ts - fix receive error The i2c_master_recv() uses readsize to receive data from i2c but compares to size of rdbuf which is always 27. This would cause problem when the max_fingers is not 5. Change the comparison value to readsize instead. Fixes: 36874c7e219 ("Input: pixcir_i2c_ts - support up to 5 fingers and hardware tracking IDs:) Cc: stable@vger.kernel.org Signed-off-by: Frodo Lai Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/pixcir_i2c_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 2c2107147319..8f3e243a62bf 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -78,7 +78,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, } ret = i2c_master_recv(tsdata->client, rdbuf, readsize); - if (ret != sizeof(rdbuf)) { + if (ret != readsize) { dev_err(&tsdata->client->dev, "%s: i2c_master_recv failed(), ret=%d\n", __func__, ret); -- cgit v1.2.3