aboutsummaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov2018-05-24 09:30:15 -0700
committerDmitry Torokhov2018-05-24 09:30:15 -0700
commit754451342fc5954061ede74b0a8485ec4a4c6eaa (patch)
tree82daccba5779de492631c42e47a614bd9d4cddd2 /drivers/input
parentbf232e460a3530adf17da7d7f1332347b73a3d08 (diff)
parent771c577c23bac90597c685971d7297ea00f99d11 (diff)
Merge tag 'v4.17-rc6' into next
Sync up with mainline to bring in Atmel controller changes for Caroline.
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/input-leds.c8
-rw-r--r--drivers/input/joystick/analog.c2
-rw-r--r--drivers/input/joystick/xpad.c9
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/bf54x-keys.c396
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c16
-rw-r--r--drivers/input/misc/Kconfig9
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/bfin_rotary.c294
-rw-r--r--drivers/input/mouse/alps.c26
-rw-r--r--drivers/input/rmi4/rmi_spi.c7
-rw-r--r--drivers/input/serio/gscps2.c11
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/touchscreen/Kconfig2
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c200
-rw-r--r--drivers/input/touchscreen/silead.c1
-rw-r--r--drivers/input/touchscreen/sur40.c178
18 files changed, 366 insertions, 811 deletions
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c
index 766bf2660116..5f04b2d94635 100644
--- a/drivers/input/input-leds.c
+++ b/drivers/input/input-leds.c
@@ -88,6 +88,7 @@ static int input_leds_connect(struct input_handler *handler,
const struct input_device_id *id)
{
struct input_leds *leds;
+ struct input_led *led;
unsigned int num_leds;
unsigned int led_code;
int led_no;
@@ -119,14 +120,13 @@ static int input_leds_connect(struct input_handler *handler,
led_no = 0;
for_each_set_bit(led_code, dev->ledbit, LED_CNT) {
- struct input_led *led = &leds->leds[led_no];
+ if (!input_led_info[led_code].name)
+ continue;
+ led = &leds->leds[led_no];
led->handle = &leds->handle;
led->code = led_code;
- if (!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);
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index c868a878c84f..c79dbcb4d146 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -163,7 +163,7 @@ static unsigned int get_time_pit(void)
#define GET_TIME(x) do { x = (unsigned int)rdtsc(); } while (0)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "TSC"
-#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV) || defined(CONFIG_TILE)
+#elif defined(__alpha__) || defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_PPC) || defined(CONFIG_RISCV)
#define GET_TIME(x) do { x = get_cycles(); } while (0)
#define DELTA(x,y) ((y)-(x))
#define TIME_NAME "get_cycles"
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index cef21b2c4e6e..f5d2b5147dd4 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -229,6 +229,7 @@ static const struct xpad_device {
{ 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
+ { 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
{ 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE },
{ 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
@@ -477,7 +478,8 @@ static const u8 xboxone_hori_init[] = {
/*
* This packet is required for some of the PDP pads to start
- * sending input reports. One of those pads is (0x0e6f:0x02ab).
+ * sending input reports. These pads include: (0x0e6f:0x02ab),
+ * (0x0e6f:0x02a4).
*/
static const u8 xboxone_pdp_init1[] = {
0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
@@ -485,7 +487,8 @@ static const u8 xboxone_pdp_init1[] = {
/*
* This packet is required for some of the PDP pads to start
- * sending input reports. One of those pads is (0x0e6f:0x02ab).
+ * sending input reports. These pads include: (0x0e6f:0x02ab),
+ * (0x0e6f:0x02a4).
*/
static const u8 xboxone_pdp_init2[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
@@ -523,6 +526,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1),
XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2),
+ XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1),
+ XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2),
XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4c4ab1ced235..2b469cc47a78 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -157,15 +157,6 @@ config KEYBOARD_QT2160
This driver can also be built as a module. If so, the module
will be called qt2160.
-config KEYBOARD_BFIN
- tristate "Blackfin BF54x keypad support"
- depends on (BF54x && !BF544)
- help
- Say Y here if you want to use the BF54x keypad.
-
- To compile this driver as a module, choose M here: the
- module will be called bf54x-keys.
-
config KEYBOARD_CLPS711X
tristate "CLPS711X Keypad support"
depends on OF_GPIO && (ARCH_CLPS711X || COMPILE_TEST)
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 526e68294e6e..8fab920afa58 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o
-obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
deleted file mode 100644
index 8a07a426f88e..000000000000
--- a/drivers/input/keyboard/bf54x-keys.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * File: drivers/input/keyboard/bf54x-keys.c
- * Based on:
- * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
- *
- * Created:
- * Description: keypad driver for Analog Devices Blackfin BF54x Processors
- *
- *
- * Modified:
- * Copyright 2007-2008 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/pm.h>
-#include <linux/sysctl.h>
-#include <linux/proc_fs.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-
-#include <asm/portmux.h>
-#include <mach/bf54x_keys.h>
-
-#define DRV_NAME "bf54x-keys"
-#define TIME_SCALE 100 /* 100 ns */
-#define MAX_MULT (0xFF * TIME_SCALE)
-#define MAX_RC 8 /* Max Row/Col */
-
-static const u16 per_rows[] = {
- P_KEY_ROW7,
- P_KEY_ROW6,
- P_KEY_ROW5,
- P_KEY_ROW4,
- P_KEY_ROW3,
- P_KEY_ROW2,
- P_KEY_ROW1,
- P_KEY_ROW0,
- 0
-};
-
-static const u16 per_cols[] = {
- P_KEY_COL7,
- P_KEY_COL6,
- P_KEY_COL5,
- P_KEY_COL4,
- P_KEY_COL3,
- P_KEY_COL2,
- P_KEY_COL1,
- P_KEY_COL0,
- 0
-};
-
-struct bf54x_kpad {
- struct input_dev *input;
- int irq;
- unsigned short lastkey;
- unsigned short *keycode;
- struct timer_list timer;
- unsigned int keyup_test_jiffies;
- unsigned short kpad_msel;
- unsigned short kpad_prescale;
- unsigned short kpad_ctl;
-};
-
-static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad,
- struct input_dev *input, u16 keyident)
-{
- u16 i;
-
- for (i = 0; i < input->keycodemax; i++)
- if (bf54x_kpad->keycode[i + input->keycodemax] == keyident)
- return bf54x_kpad->keycode[i];
- return -1;
-}
-
-static inline void bfin_keycodecpy(unsigned short *keycode,
- const unsigned int *pdata_kc,
- unsigned short keymapsize)
-{
- unsigned int i;
-
- for (i = 0; i < keymapsize; i++) {
- keycode[i] = pdata_kc[i] & 0xffff;
- keycode[i + keymapsize] = pdata_kc[i] >> 16;
- }
-}
-
-static inline u16 bfin_kpad_get_prescale(u32 timescale)
-{
- u32 sclk = get_sclk();
-
- return ((((sclk / 1000) * timescale) / 1024) - 1);
-}
-
-static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad)
-{
- return (bfin_read_KPAD_STAT() & KPAD_PRESSED);
-}
-
-static inline void bfin_kpad_clear_irq(void)
-{
- bfin_write_KPAD_STAT(0xFFFF);
- bfin_write_KPAD_ROWCOL(0xFFFF);
-}
-
-static void bfin_kpad_timer(struct timer_list *t)
-{
- struct bf54x_kpad *bf54x_kpad = from_timer(bf54x_kpad, t, timer);
-
- if (bfin_kpad_get_keypressed(bf54x_kpad)) {
- /* Try again later */
- mod_timer(&bf54x_kpad->timer,
- jiffies + bf54x_kpad->keyup_test_jiffies);
- return;
- }
-
- input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0);
- input_sync(bf54x_kpad->input);
-
- /* Clear IRQ Status */
-
- bfin_kpad_clear_irq();
- enable_irq(bf54x_kpad->irq);
-}
-
-static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
-{
- struct platform_device *pdev = dev_id;
- struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
- struct input_dev *input = bf54x_kpad->input;
- int key;
- u16 rowcol = bfin_read_KPAD_ROWCOL();
-
- key = bfin_kpad_find_key(bf54x_kpad, input, rowcol);
-
- input_report_key(input, key, 1);
- input_sync(input);
-
- if (bfin_kpad_get_keypressed(bf54x_kpad)) {
- disable_irq_nosync(bf54x_kpad->irq);
- bf54x_kpad->lastkey = key;
- mod_timer(&bf54x_kpad->timer,
- jiffies + bf54x_kpad->keyup_test_jiffies);
- } else {
- input_report_key(input, key, 0);
- input_sync(input);
-
- bfin_kpad_clear_irq();
- }
-
- return IRQ_HANDLED;
-}
-
-static int bfin_kpad_probe(struct platform_device *pdev)
-{
- struct bf54x_kpad *bf54x_kpad;
- struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct input_dev *input;
- int i, error;
-
- if (!pdata->rows || !pdata->cols || !pdata->keymap) {
- dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n");
- return -EINVAL;
- }
-
- if (!pdata->keymapsize ||
- pdata->keymapsize > (pdata->rows * pdata->cols)) {
- dev_err(&pdev->dev, "invalid keymapsize\n");
- return -EINVAL;
- }
-
- bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL);
- if (!bf54x_kpad)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, bf54x_kpad);
-
- /* Allocate memory for keymap followed by private LUT */
- bf54x_kpad->keycode = kmalloc(pdata->keymapsize *
- sizeof(unsigned short) * 2, GFP_KERNEL);
- if (!bf54x_kpad->keycode) {
- error = -ENOMEM;
- goto out;
- }
-
- if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT ||
- !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) {
- dev_warn(&pdev->dev,
- "invalid platform debounce/columndrive time\n");
- bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */
- } else {
- bfin_write_KPAD_MSEL(
- ((pdata->debounce_time / TIME_SCALE)
- & DBON_SCALE) |
- (((pdata->coldrive_time / TIME_SCALE) << 8)
- & COLDRV_SCALE));
-
- }
-
- if (!pdata->keyup_test_interval)
- bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50);
- else
- bf54x_kpad->keyup_test_jiffies =
- msecs_to_jiffies(pdata->keyup_test_interval);
-
- if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows],
- DRV_NAME)) {
- dev_err(&pdev->dev, "requesting peripherals failed\n");
- error = -EFAULT;
- goto out0;
- }
-
- if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols],
- DRV_NAME)) {
- dev_err(&pdev->dev, "requesting peripherals failed\n");
- error = -EFAULT;
- goto out1;
- }
-
- bf54x_kpad->irq = platform_get_irq(pdev, 0);
- if (bf54x_kpad->irq < 0) {
- error = -ENODEV;
- goto out2;
- }
-
- error = request_irq(bf54x_kpad->irq, bfin_kpad_isr,
- 0, DRV_NAME, pdev);
- if (error) {
- dev_err(&pdev->dev, "unable to claim irq %d\n",
- bf54x_kpad->irq);
- goto out2;
- }
-
- input = input_allocate_device();
- if (!input) {
- error = -ENOMEM;
- goto out3;
- }
-
- bf54x_kpad->input = input;
-
- input->name = pdev->name;
- input->phys = "bf54x-keys/input0";
- input->dev.parent = &pdev->dev;
-
- input->id.bustype = BUS_HOST;
- input->id.vendor = 0x0001;
- input->id.product = 0x0001;
- input->id.version = 0x0100;
-
- input->keycodesize = sizeof(unsigned short);
- input->keycodemax = pdata->keymapsize;
- input->keycode = bf54x_kpad->keycode;
-
- bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize);
-
- /* setup input device */
- __set_bit(EV_KEY, input->evbit);
-
- if (pdata->repeat)
- __set_bit(EV_REP, input->evbit);
-
- for (i = 0; i < input->keycodemax; i++)
- if (bf54x_kpad->keycode[i] <= KEY_MAX)
- __set_bit(bf54x_kpad->keycode[i], input->keybit);
- __clear_bit(KEY_RESERVED, input->keybit);
-
- error = input_register_device(input);
- if (error) {
- dev_err(&pdev->dev, "unable to register input device\n");
- goto out4;
- }
-
- /* Init Keypad Key Up/Release test timer */
-
- timer_setup(&bf54x_kpad->timer, bfin_kpad_timer, 0);
-
- bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE));
-
- bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) |
- (((pdata->rows - 1) << 10) & KPAD_ROWEN) |
- (2 & KPAD_IRQMODE));
-
- bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
-
- device_init_wakeup(&pdev->dev, 1);
-
- return 0;
-
-out4:
- input_free_device(input);
-out3:
- free_irq(bf54x_kpad->irq, pdev);
-out2:
- peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
-out1:
- peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
-out0:
- kfree(bf54x_kpad->keycode);
-out:
- kfree(bf54x_kpad);
-
- return error;
-}
-
-static int bfin_kpad_remove(struct platform_device *pdev)
-{
- struct bfin_kpad_platform_data *pdata = dev_get_platdata(&pdev->dev);
- struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
-
- del_timer_sync(&bf54x_kpad->timer);
- free_irq(bf54x_kpad->irq, pdev);
-
- input_unregister_device(bf54x_kpad->input);
-
- peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
- peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
-
- kfree(bf54x_kpad->keycode);
- kfree(bf54x_kpad);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
-
- bf54x_kpad->kpad_msel = bfin_read_KPAD_MSEL();
- bf54x_kpad->kpad_prescale = bfin_read_KPAD_PRESCALE();
- bf54x_kpad->kpad_ctl = bfin_read_KPAD_CTL();
-
- if (device_may_wakeup(&pdev->dev))
- enable_irq_wake(bf54x_kpad->irq);
-
- return 0;
-}
-
-static int bfin_kpad_resume(struct platform_device *pdev)
-{
- struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
-
- bfin_write_KPAD_MSEL(bf54x_kpad->kpad_msel);
- bfin_write_KPAD_PRESCALE(bf54x_kpad->kpad_prescale);
- bfin_write_KPAD_CTL(bf54x_kpad->kpad_ctl);
-
- if (device_may_wakeup(&pdev->dev))
- disable_irq_wake(bf54x_kpad->irq);
-
- return 0;
-}
-#else
-# define bfin_kpad_suspend NULL
-# define bfin_kpad_resume NULL
-#endif
-
-static struct platform_driver bfin_kpad_device_driver = {
- .driver = {
- .name = DRV_NAME,
- },
- .probe = bfin_kpad_probe,
- .remove = bfin_kpad_remove,
- .suspend = bfin_kpad_suspend,
- .resume = bfin_kpad_resume,
-};
-module_platform_driver(bfin_kpad_device_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
-MODULE_ALIAS("platform:bf54x-keys");
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 8c6c0b9109c7..d69e631cfa0a 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -48,6 +48,14 @@
#define STMPE_KEYPAD_KEYMAP_MAX_SIZE \
(STMPE_KEYPAD_MAX_ROWS * STMPE_KEYPAD_MAX_COLS)
+
+#define STMPE1601_NUM_DATA 5
+#define STMPE2401_NUM_DATA 3
+#define STMPE2403_NUM_DATA 5
+
+/* Make sure it covers all cases above */
+#define MAX_NUM_DATA 5
+
/**
* struct stmpe_keypad_variant - model-specific attributes
* @auto_increment: whether the KPC_DATA_BYTE register address
@@ -74,7 +82,7 @@ struct stmpe_keypad_variant {
static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE1601] = {
.auto_increment = true,
- .num_data = 5,
+ .num_data = STMPE1601_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 8,
@@ -84,7 +92,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2401] = {
.auto_increment = false,
.set_pullup = true,
- .num_data = 3,
+ .num_data = STMPE2401_NUM_DATA,
.num_normal_data = 2,
.max_cols = 8,
.max_rows = 12,
@@ -94,7 +102,7 @@ static const struct stmpe_keypad_variant stmpe_keypad_variants[] = {
[STMPE2403] = {
.auto_increment = true,
.set_pullup = true,
- .num_data = 5,
+ .num_data = STMPE2403_NUM_DATA,
.num_normal_data = 3,
.max_cols = 8,
.max_rows = 12,
@@ -156,7 +164,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev)
struct stmpe_keypad *keypad = dev;
struct input_dev *input = keypad->input;
const struct stmpe_keypad_variant *variant = keypad->variant;
- u8 fifo[variant->num_data];
+ u8 fifo[MAX_NUM_DATA];
int ret;
int i;
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 6a3c753b093b..572b15fa18c2 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -655,15 +655,6 @@ config INPUT_DM355EVM
To compile this driver as a module, choose M here: the
module will be called dm355evm_keys.
-config INPUT_BFIN_ROTARY
- tristate "Blackfin Rotary support"
- depends on BF54x || BF52x
- help
- Say Y here if you want to use the Blackfin Rotary.
-
- To compile this driver as a module, choose M here: the
- module will be called bfin-rotary.
-
config INPUT_WM831X_ON
tristate "WM831X ON pin"
depends on MFD_WM831X
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 8cc58f362bb8..72cde28649e2 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_INPUT_ARIZONA_HAPTICS) += arizona-haptics.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o
obj-$(CONFIG_INPUT_ATMEL_CAPTOUCH) += atmel_captouch.o
-obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o
obj-$(CONFIG_INPUT_BMA150) += bma150.o
obj-$(CONFIG_INPUT_CM109) += cm109.o
obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c
deleted file mode 100644
index 799ce3d2820e..000000000000
--- a/drivers/input/misc/bfin_rotary.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Rotary counter driver for Analog Devices Blackfin Processors
- *
- * Copyright 2008-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/platform_data/bfin_rotary.h>
-
-#include <asm/portmux.h>
-
-#define CNT_CONFIG_OFF 0 /* CNT Config Offset */
-#define CNT_IMASK_OFF 4 /* CNT Interrupt Mask Offset */
-#define CNT_STATUS_OFF 8 /* CNT Status Offset */
-#define CNT_COMMAND_OFF 12 /* CNT Command Offset */
-#define CNT_DEBOUNCE_OFF 16 /* CNT Debounce Offset */
-#define CNT_COUNTER_OFF 20 /* CNT Counter Offset */
-#define CNT_MAX_OFF 24 /* CNT Maximum Count Offset */
-#define CNT_MIN_OFF 28 /* CNT Minimum Count Offset */
-
-struct bfin_rot {
- struct input_dev *input;
- void __iomem *base;
- int irq;
- unsigned int up_key;
- unsigned int down_key;
- unsigned int button_key;
- unsigned int rel_code;
-
- unsigned short mode;
- unsigned short debounce;
-
- unsigned short cnt_config;
- unsigned short cnt_imask;
- unsigned short cnt_debounce;
-};
-
-static void report_key_event(struct input_dev *input, int keycode)
-{
- /* simulate a press-n-release */
- input_report_key(input, keycode, 1);
- input_sync(input);
- input_report_key(input, keycode, 0);
- input_sync(input);
-}
-
-static void report_rotary_event(struct bfin_rot *rotary, int delta)
-{
- struct input_dev *input = rotary->input;
-
- if (rotary->up_key) {
- report_key_event(input,
- delta > 0 ? rotary->up_key : rotary->down_key);
- } else {
- input_report_rel(input, rotary->rel_code, delta);
- input_sync(input);
- }
-}
-
-static irqreturn_t bfin_rotary_isr(int irq, void *dev_id)
-{
- struct bfin_rot *rotary = dev_id;
- int delta;
-
- switch (readw(rotary->base + CNT_STATUS_OFF)) {
-
- case ICII:
- break;
-
- case UCII:
- case DCII:
- delta = readl(rotary->base + CNT_COUNTER_OFF);
- if (delta)
- report_rotary_event(rotary, delta);
- break;
-
- case CZMII:
- report_key_event(rotary->input, rotary->button_key);
- break;
-
- default:
- break;
- }
-
- writew(W1LCNT_ZERO, rotary->base + CNT_COMMAND_OFF); /* Clear COUNTER */
- writew(-1, rotary->base + CNT_STATUS_OFF); /* Clear STATUS */
-
- return IRQ_HANDLED;
-}
-
-static int bfin_rotary_open(struct input_dev *input)
-{
- struct bfin_rot *rotary = input_get_drvdata(input);
- unsigned short val;
-
- if (rotary->mode & ROT_DEBE)
- writew(rotary->debounce & DPRESCALE,
- rotary->base + CNT_DEBOUNCE_OFF);
-
- writew(rotary->mode & ~CNTE, rotary->base + CNT_CONFIG_OFF);
-
- val = UCIE | DCIE;
- if (rotary->button_key)
- val |= CZMIE;
- writew(val, rotary->base + CNT_IMASK_OFF);
-
- writew(rotary->mode | CNTE, rotary->base + CNT_CONFIG_OFF);
-
- return 0;
-}
-
-static void bfin_rotary_close(struct input_dev *input)
-{
- struct bfin_rot *rotary = input_get_drvdata(input);
-
- writew(0, rotary->base + CNT_CONFIG_OFF);
- writew(0, rotary->base + CNT_IMASK_OFF);
-}
-
-static void bfin_rotary_free_action(void *data)
-{
- peripheral_free_list(data);
-}
-
-static int bfin_rotary_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- const struct bfin_rotary_platform_data *pdata = dev_get_platdata(dev);
- struct bfin_rot *rotary;
- struct resource *res;
- struct input_dev *input;
- int error;
-
- /* Basic validation */
- if ((pdata->rotary_up_key && !pdata->rotary_down_key) ||
- (!pdata->rotary_up_key && pdata->rotary_down_key)) {
- return -EINVAL;
- }
-
- if (pdata->pin_list) {
- error = peripheral_request_list(pdata->pin_list,
- dev_name(dev));
- if (error) {
- dev_err(dev, "requesting peripherals failed: %d\n",
- error);
- return error;
- }
-
- error = devm_add_action_or_reset(dev, bfin_rotary_free_action,
- pdata->pin_list);
- if (error) {
- dev_err(dev, "setting cleanup action failed: %d\n",
- error);
- return error;
- }
- }
-
- rotary = devm_kzalloc(dev, sizeof(struct bfin_rot), GFP_KERNEL);
- if (!rotary)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rotary->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(rotary->base))
- return PTR_ERR(rotary->base);
-
- input = devm_input_allocate_device(dev);
- if (!input)
- return -ENOMEM;
-
- rotary->input = input;
-
- rotary->up_key = pdata->rotary_up_key;
- rotary->down_key = pdata->rotary_down_key;
- rotary->button_key = pdata->rotary_button_key;
- rotary->rel_code = pdata->rotary_rel_code;
-
- rotary->mode = pdata->mode;
- rotary->debounce = pdata->debounce;
-
- input->name = pdev->name;
- input->phys = "bfin-rotary/input0";
- input->dev.parent = dev;
-
- input_set_drvdata(input, rotary);
-
- input->id.bustype = BUS_HOST;
- input->id.vendor = 0x0001;
- input->id.product = 0x0001;
- input->id.version = 0x0100;
-
- input->open = bfin_rotary_open;
- input->close = bfin_rotary_close;
-
- if (rotary->up_key) {
- __set_bit(EV_KEY, input->evbit);
- __set_bit(rotary->up_key, input->keybit);
- __set_bit(rotary->down_key, input->keybit);
- } else {
- __set_bit(EV_REL, input->evbit);
- __set_bit(rotary->rel_code, input->relbit);
- }
-
- if (rotary->button_key) {
- __set_bit(EV_KEY, input->evbit);
- __set_bit(rotary->button_key, input->keybit);
- }
-
- /* Quiesce the device before requesting irq */
- bfin_rotary_close(input);
-
- rotary->irq = platform_get_irq(pdev, 0);
- if (rotary->irq < 0) {
- dev_err(dev, "No rotary IRQ specified\n");
- return -ENOENT;
- }
-
- error = devm_request_irq(dev, rotary->irq, bfin_rotary_isr,
- 0, dev_name(dev), rotary);
- if (error) {
- dev_err(dev, "unable to claim irq %d; error %d\n",
- rotary->irq, error);
- return error;
- }
-
- error = input_register_device(input);
- if (error) {
- dev_err(dev, "unable to register input device (%d)\n", error);
- return error;
- }
-
- platform_set_drvdata(pdev, rotary);
- device_init_wakeup(dev, 1);
-
- return 0;
-}
-
-static int __maybe_unused bfin_rotary_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct bfin_rot *rotary = platform_get_drvdata(pdev);
-
- rotary->cnt_config = readw(rotary->base + CNT_CONFIG_OFF);
- rotary->cnt_imask = readw(rotary->base + CNT_IMASK_OFF);
- rotary->cnt_debounce = readw(rotary->base + CNT_DEBOUNCE_OFF);
-
- if (device_may_wakeup(&pdev->dev))
- enable_irq_wake(rotary->irq);
-
- return 0;
-}
-
-static int __maybe_unused bfin_rotary_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct bfin_rot *rotary = platform_get_drvdata(pdev);
-
- writew(rotary->cnt_debounce, rotary->base + CNT_DEBOUNCE_OFF);
- writew(rotary->cnt_imask, rotary->base + CNT_IMASK_OFF);
- writew(rotary->cnt_config & ~CNTE, rotary->base + CNT_CONFIG_OFF);
-
- if (device_may_wakeup(&pdev->dev))
- disable_irq_wake(rotary->irq);
-
- if (rotary->cnt_config & CNTE)
- writew(rotary->cnt_config, rotary->base + CNT_CONFIG_OFF);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(bfin_rotary_pm_ops,
- bfin_rotary_suspend, bfin_rotary_resume);
-
-static struct platform_driver bfin_rotary_device_driver = {
- .probe = bfin_rotary_probe,
- .driver = {
- .name = "bfin-rotary",
- .pm = &bfin_rotary_pm_ops,
- },
-};
-module_platform_driver(bfin_rotary_device_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors");
-MODULE_ALIAS("platform:bfin-rotary");
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index adf7f05c643a..cb5579716dba 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -583,7 +583,7 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
- z = packet[4] & 0x7c;
+ z = packet[4] & 0x7f;
/*
* The x and y values tend to be quite large, and when used
@@ -2548,13 +2548,31 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
}
static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
- struct alps_data *priv)
+ struct alps_data *priv,
+ struct psmouse *psmouse)
{
bool is_dual = false;
+ int reg_val = 0;
+ struct ps2dev *ps2dev = &psmouse->ps2dev;
- if (IS_SS4PLUS_DEV(priv->dev_id))
+ if (IS_SS4PLUS_DEV(priv->dev_id)) {
is_dual = (otp[0][0] >> 4) & 0x01;
+ if (!is_dual) {
+ /* For support TrackStick of Thinkpad L/E series */
+ if (alps_exit_command_mode(psmouse) == 0 &&
+ alps_enter_command_mode(psmouse) == 0) {
+ reg_val = alps_command_mode_read_reg(psmouse,
+ 0xD7);
+ }
+ alps_exit_command_mode(psmouse);
+ ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+
+ if (reg_val == 0x0C || reg_val == 0x1D)
+ is_dual = true;
+ }
+ }
+
if (is_dual)
priv->flags |= ALPS_DUALPOINT |
ALPS_DUALPOINT_WITH_PRESSURE;
@@ -2577,7 +2595,7 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
alps_update_btn_info_ss4_v2(otp, priv);
- alps_update_dual_info_ss4_v2(otp, priv);
+ alps_update_dual_info_ss4_v2(otp, priv, psmouse);
return 0;
}
diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c
index 76edbf2c1bce..082defc329a8 100644
--- a/drivers/input/rmi4/rmi_spi.c
+++ b/drivers/input/rmi4/rmi_spi.c
@@ -147,8 +147,11 @@ static int rmi_spi_xfer(struct rmi_spi_xport *rmi_spi,
if (len > RMI_SPI_XFER_SIZE_LIMIT)
return -EINVAL;
- if (rmi_spi->xfer_buf_size < len)
- rmi_spi_manage_pools(rmi_spi, len);
+ if (rmi_spi->xfer_buf_size < len) {
+ ret = rmi_spi_manage_pools(rmi_spi, len);
+ if (ret < 0)
+ return ret;
+ }
if (addr == 0)
/*
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index aa9f29b875de..49d8d53e50b7 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -91,7 +91,7 @@ struct gscps2port {
struct parisc_device *padev;
struct serio *port;
spinlock_t lock;
- char *addr;
+ char __iomem *addr;
u8 act, append; /* position in buffer[] */
struct {
u8 data;
@@ -114,7 +114,7 @@ struct gscps2port {
* wait_TBE() - wait for Transmit Buffer Empty
*/
-static int wait_TBE(char *addr)
+static int wait_TBE(char __iomem *addr)
{
int timeout = 25000; /* device is expected to react within 250 msec */
while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
@@ -146,14 +146,14 @@ static void gscps2_flush(struct gscps2port *ps2port)
static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
{
unsigned long flags;
- char *addr = ps2port->addr;
+ char __iomem *addr = ps2port->addr;
if (!wait_TBE(addr)) {
printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data);
return 0;
}
- while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
+ while (gscps2_readb_status(addr) & GSC_STAT_RBNE)
/* wait */;
spin_lock_irqsave(&ps2port->lock, flags);
@@ -200,13 +200,12 @@ static void gscps2_enable(struct gscps2port *ps2port, int enable)
static void gscps2_reset(struct gscps2port *ps2port)
{
- char *addr = ps2port->addr;
unsigned long flags;
/* reset the interface */
spin_lock_irqsave(&ps2port->lock, flags);
gscps2_flush(ps2port);
- writeb(0xff, addr+GSC_RESET);
+ writeb(0xff, ps2port->addr + GSC_RESET);
gscps2_flush(ps2port);
spin_unlock_irqrestore(&ps2port->lock, flags);
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 87e84a085a23..b353d494ad40 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -635,6 +635,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
},
},
{
+ /* Lenovo ThinkPad L460 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),
+ },
+ },
+ {
/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 94cc740a4203..32267c1afebc 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -373,7 +373,7 @@ config TOUCHSCREEN_HIDEEP
If unsure, say N.
- To compile this driver as a moudle, choose M here : the
+ To compile this driver as a module, choose M here : the
module will be called hideep_ts.
config TOUCHSCREEN_ILI210X
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 5d9699fe1b55..09194721aed2 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -280,7 +280,8 @@ struct mxt_data {
struct input_dev *input_dev;
char phys[64]; /* device physical location */
struct mxt_object *object_table;
- struct mxt_info info;
+ struct mxt_info *info;
+ void *raw_info_block;
unsigned int irq;
unsigned int max_x;
unsigned int max_y;
@@ -460,12 +461,13 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
{
u8 appmode = data->client->addr;
u8 bootloader;
+ u8 family_id = data->info ? data->info->family_id : 0;
switch (appmode) {
case 0x4a:
case 0x4b:
/* Chips after 1664S use different scheme */
- if (retry || data->info.family_id >= 0xa2) {
+ if (retry || family_id >= 0xa2) {
bootloader = appmode - 0x24;
break;
}
@@ -692,7 +694,7 @@ mxt_get_object(struct mxt_data *data, u8 type)
struct mxt_object *object;
int i;
- for (i = 0; i < data->info.object_num; i++) {
+ for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i;
if (object->type == type)
return object;
@@ -1462,12 +1464,12 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
data_pos += offset;
}
- if (cfg_info.family_id != data->info.family_id) {
+ if (cfg_info.family_id != data->info->family_id) {
dev_err(dev, "Family ID mismatch!\n");
return -EINVAL;
}
- if (cfg_info.variant_id != data->info.variant_id) {
+ if (cfg_info.variant_id != data->info->variant_id) {
dev_err(dev, "Variant ID mismatch!\n");
return -EINVAL;
}
@@ -1512,7 +1514,7 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
/* Malloc memory to store configuration */
cfg_start_ofs = MXT_OBJECT_START +
- data->info.object_num * sizeof(struct mxt_object) +
+ data->info->object_num * sizeof(struct mxt_object) +
MXT_INFO_CHECKSUM_SIZE;
config_mem_size = data->mem_size - cfg_start_ofs;
config_mem = kzalloc(config_mem_size, GFP_KERNEL);
@@ -1563,20 +1565,6 @@ release_mem:
return ret;
}
-static int mxt_get_info(struct mxt_data *data)
-{
- struct i2c_client *client = data->client;
- struct mxt_info *info = &data->info;
- int error;
-
- /* Read 7-byte info block starting at address 0 */
- error = __mxt_read_reg(client, 0, sizeof(*info), info);
- if (error)
- return error;
-
- return 0;
-}
-
static void mxt_free_input_device(struct mxt_data *data)
{
if (data->input_dev) {
@@ -1591,9 +1579,10 @@ static void mxt_free_object_table(struct mxt_data *data)
video_unregister_device(&data->dbg.vdev);
v4l2_device_unregister(&data->dbg.v4l2);
#endif
-
- kfree(data->object_table);
data->object_table = NULL;
+ data->info = NULL;
+ kfree(data->raw_info_block);
+ data->raw_info_block = NULL;
kfree(data->msg_buf);
data->msg_buf = NULL;
data->T5_address = 0;
@@ -1609,34 +1598,18 @@ static void mxt_free_object_table(struct mxt_data *data)
data->max_reportid = 0;
}
-static int mxt_get_object_table(struct mxt_data *data)
+static int mxt_parse_object_table(struct mxt_data *data,
+ struct mxt_object *object_table)
{
struct i2c_client *client = data->client;
- size_t table_size;
- struct mxt_object *object_table;
- int error;
int i;
u8 reportid;
u16 end_address;
- table_size = data->info.object_num * sizeof(struct mxt_object);
- object_table = kzalloc(table_size, GFP_KERNEL);
- if (!object_table) {
- dev_err(&data->client->dev, "Failed to allocate memory\n");
- return -ENOMEM;
- }
-
- error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
- object_table);
- if (error) {
- kfree(object_table);
- return error;
- }
-
/* Valid Report IDs start counting from 1 */
reportid = 1;
data->mem_size = 0;
- for (i = 0; i < data->info.object_num; i++) {
+ for (i = 0; i < data->info->object_num; i++) {
struct mxt_object *object = object_table + i;
u8 min_id, max_id;
@@ -1660,8 +1633,8 @@ static int mxt_get_object_table(struct mxt_data *data)
switch (object->type) {
case MXT_GEN_MESSAGE_T5:
- if (data->info.family_id == 0x80 &&
- data->info.version < 0x20) {
+ if (data->info->family_id == 0x80 &&
+ data->info->version < 0x20) {
/*
* On mXT224 firmware versions prior to V2.0
* read and discard unused CRC byte otherwise
@@ -1716,24 +1689,102 @@ static int mxt_get_object_table(struct mxt_data *data)
/* If T44 exists, T5 position has to be directly after */
if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
dev_err(&client->dev, "Invalid T44 position\n");
- error = -EINVAL;
- goto free_object_table;
+ return -EINVAL;
}
data->msg_buf = kcalloc(data->max_reportid,
data->T5_msg_size, GFP_KERNEL);
- if (!data->msg_buf) {
- dev_err(&client->dev, "Failed to allocate message buffer\n");
+ if (!data->msg_buf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int mxt_read_info_block(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ int error;
+ size_t size;
+ void *id_buf, *buf;
+ uint8_t num_objects;
+ u32 calculated_crc;
+ u8 *crc_ptr;
+
+ /* If info block already allocated, free it */
+ if (data->raw_info_block)
+ mxt_free_object_table(data);
+
+ /* Read 7-byte ID information block starting at address 0 */
+ size = sizeof(struct mxt_info);
+ id_buf = kzalloc(size, GFP_KERNEL);
+ if (!id_buf)
+ return -ENOMEM;
+
+ error = __mxt_read_reg(client, 0, size, id_buf);
+ if (error)
+ goto err_free_mem;
+
+ /* Resize buffer to give space for rest of info block */
+ num_objects = ((struct mxt_info *)id_buf)->object_num;
+ size += (num_objects * sizeof(struct mxt_object))
+ + MXT_INFO_CHECKSUM_SIZE;
+
+ buf = krealloc(id_buf, size, GFP_KERNEL);
+ if (!buf) {
error = -ENOMEM;
- goto free_object_table;
+ goto err_free_mem;
+ }
+ id_buf = buf;
+
+ /* Read rest of info block */
+ error = __mxt_read_reg(client, MXT_OBJECT_START,
+ size - MXT_OBJECT_START,
+ id_buf + MXT_OBJECT_START);
+ if (error)
+ goto err_free_mem;
+
+ /* Extract & calculate checksum */
+ crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE;
+ data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16);
+
+ calculated_crc = mxt_calculate_crc(id_buf, 0,
+ size - MXT_INFO_CHECKSUM_SIZE);
+
+ /*
+ * CRC mismatch can be caused by data corruption due to I2C comms
+ * issue or else device is not using Object Based Protocol (eg i2c-hid)
+ */
+ if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) {
+ dev_err(&client->dev,
+ "Info Block CRC error calculated=0x%06X read=0x%06X\n",
+ calculated_crc, data->info_crc);
+ error = -EIO;
+ goto err_free_mem;
+ }
+
+ data->raw_info_block = id_buf;
+ data->info = (struct mxt_info *)id_buf;
+
+ dev_info(&client->dev,
+ "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
+ data->info->family_id, data->info->variant_id,
+ data->info->version >> 4, data->info->version & 0xf,
+ data->info->build, data->info->object_num);
+
+ /* Parse object table information */
+ error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START);
+ if (error) {
+ dev_err(&client->dev, "Error %d parsing object table\n", error);
+ mxt_free_object_table(data);
+ goto err_free_mem;
}
- data->object_table = object_table;
+ data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
return 0;
-free_object_table:
- mxt_free_object_table(data);
+err_free_mem:
+ kfree(id_buf);
return error;
}
@@ -2046,7 +2097,7 @@ static int mxt_initialize(struct mxt_data *data)
int error;
while (1) {
- error = mxt_get_info(data);
+ error = mxt_read_info_block(data);
if (!error)
break;
@@ -2077,16 +2128,9 @@ static int mxt_initialize(struct mxt_data *data)
msleep(MXT_FW_RESET_TIME);
}
- /* Get object table information */
- error = mxt_get_object_table(data);
- if (error) {
- dev_err(&client->dev, "Error %d reading object table\n", error);
- return error;
- }
-
error = mxt_acquire_irq(data);
if (error)
- goto err_free_object_table;
+ return error;
error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
&client->dev, GFP_KERNEL, data,
@@ -2094,14 +2138,10 @@ static int mxt_initialize(struct mxt_data *data)
if (error) {
dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
error);
- goto err_free_object_table;
+ return error;
}
return 0;
-
-err_free_object_table:
- mxt_free_object_table(data);
- return error;
}
static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
@@ -2162,7 +2202,7 @@ recheck:
static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
unsigned int y)
{
- struct mxt_info *info = &data->info;
+ struct mxt_info *info = data->info;
struct mxt_dbg *dbg = &data->dbg;
unsigned int ofs, page;
unsigned int col = 0;
@@ -2490,7 +2530,7 @@ static const struct video_device mxt_video_device = {
static void mxt_debug_init(struct mxt_data *data)
{
- struct mxt_info *info = &data->info;
+ struct mxt_info *info = data->info;
struct mxt_dbg *dbg = &data->dbg;
struct mxt_object *object;
int error;
@@ -2576,7 +2616,6 @@ static int mxt_configure_objects(struct mxt_data *data,
const struct firmware *cfg)
{
struct device *dev = &data->client->dev;
- struct mxt_info *info = &data->info;
int error;
error = mxt_init_t7_power_cfg(data);
@@ -2601,11 +2640,6 @@ static int mxt_configure_objects(struct mxt_data *data,
mxt_debug_init(data);
- dev_info(dev,
- "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
- info->family_id, info->variant_id, info->version >> 4,
- info->version & 0xf, info->build, info->object_num);
-
return 0;
}
@@ -2614,7 +2648,7 @@ static ssize_t mxt_fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mxt_data *data = dev_get_drvdata(dev);
- struct mxt_info *info = &data->info;
+ struct mxt_info *info = data->info;
return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
info->version >> 4, info->version & 0xf, info->build);
}
@@ -2624,7 +2658,7 @@ static ssize_t mxt_hw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mxt_data *data = dev_get_drvdata(dev);
- struct mxt_info *info = &data->info;
+ struct mxt_info *info = data->info;
return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
info->family_id, info->variant_id);
}
@@ -2663,7 +2697,7 @@ static ssize_t mxt_object_show(struct device *dev,
return -ENOMEM;
error = 0;
- for (i = 0; i < data->info.object_num; i++) {
+ for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i;
if (!mxt_object_readable(object->type))
@@ -3035,6 +3069,15 @@ static const struct dmi_system_id mxt_dmi_table[] = {
.driver_data = samus_platform_data,
},
{
+ /* Samsung Chromebook Pro */
+ .ident = "Samsung Chromebook Pro",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"),
+ },
+ .driver_data = samus_platform_data,
+ },
+ {
/* Other Google Chromebooks */
.ident = "Chromebook",
.matches = {
@@ -3254,6 +3297,11 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
static const struct of_device_id mxt_of_match[] = {
{ .compatible = "atmel,maxtouch", },
+ /* Compatibles listed below are deprecated */
+ { .compatible = "atmel,qt602240_ts", },
+ { .compatible = "atmel,atmel_mxt_ts", },
+ { .compatible = "atmel,atmel_mxt_tp", },
+ { .compatible = "atmel,mXT224", },
{},
};
MODULE_DEVICE_TABLE(of, mxt_of_match);
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index 646b1e768e6b..ff7043f74a3d 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -602,6 +602,7 @@ static const struct acpi_device_id silead_ts_acpi_match[] = {
{ "GSL3675", 0 },
{ "GSL3692", 0 },
{ "MSSL1680", 0 },
+ { "MSSL0001", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match);
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index f16f8358c70a..894843a7ec7b 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -38,6 +38,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
@@ -81,7 +82,10 @@ struct sur40_blob {
__le32 area; /* size in pixels/pressure (?) */
- u8 padding[32];
+ u8 padding[24];
+
+ __le32 tag_id; /* valid when type == 0x04 (SUR40_TAG) */
+ __le32 unknown;
} __packed;
@@ -146,6 +150,40 @@ struct sur40_image_header {
#define SUR40_TOUCH 0x02
#define SUR40_TAG 0x04
+/* video controls */
+#define SUR40_BRIGHTNESS_MAX 0xff
+#define SUR40_BRIGHTNESS_MIN 0x00
+#define SUR40_BRIGHTNESS_DEF 0xff
+
+#define SUR40_CONTRAST_MAX 0x0f
+#define SUR40_CONTRAST_MIN 0x00
+#define SUR40_CONTRAST_DEF 0x0a
+
+#define SUR40_GAIN_MAX 0x09
+#define SUR40_GAIN_MIN 0x00
+#define SUR40_GAIN_DEF 0x08
+
+#define SUR40_BACKLIGHT_MAX 0x01
+#define SUR40_BACKLIGHT_MIN 0x00
+#define SUR40_BACKLIGHT_DEF 0x01
+
+#define sur40_str(s) #s
+#define SUR40_PARAM_RANGE(lo, hi) " (range " sur40_str(lo) "-" sur40_str(hi) ")"
+
+/* module parameters */
+static uint brightness = SUR40_BRIGHTNESS_DEF;
+module_param(brightness, uint, 0644);
+MODULE_PARM_DESC(brightness, "set initial brightness"
+ SUR40_PARAM_RANGE(SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX));
+static uint contrast = SUR40_CONTRAST_DEF;
+module_param(contrast, uint, 0644);
+MODULE_PARM_DESC(contrast, "set initial contrast"
+ SUR40_PARAM_RANGE(SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX));
+static uint gain = SUR40_GAIN_DEF;
+module_param(gain, uint, 0644);
+MODULE_PARM_DESC(gain, "set initial gain"
+ SUR40_PARAM_RANGE(SUR40_GAIN_MIN, SUR40_GAIN_MAX));
+
static const struct v4l2_pix_format sur40_pix_format[] = {
{
.pixelformat = V4L2_TCH_FMT_TU08,
@@ -178,6 +216,7 @@ struct sur40_state {
struct video_device vdev;
struct mutex lock;
struct v4l2_pix_format pix_fmt;
+ struct v4l2_ctrl_handler hdl;
struct vb2_queue queue;
struct list_head buf_list;
@@ -187,6 +226,7 @@ struct sur40_state {
struct sur40_data *bulk_in_buffer;
size_t bulk_in_size;
u8 bulk_in_epaddr;
+ u8 vsvideo;
char phys[64];
};
@@ -200,6 +240,11 @@ struct sur40_buffer {
static const struct video_device sur40_video_device;
static const struct vb2_queue sur40_queue;
static void sur40_process_video(struct sur40_state *sur40);
+static int sur40_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops sur40_ctrl_ops = {
+ .s_ctrl = sur40_s_ctrl,
+};
/*
* Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
@@ -220,6 +265,81 @@ static int sur40_command(struct sur40_state *dev,
0x00, index, buffer, size, 1000);
}
+/* poke a byte in the panel register space */
+static int sur40_poke(struct sur40_state *dev, u8 offset, u8 value)
+{
+ int result;
+ u8 index = 0x96; // 0xae for permanent write
+
+ result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
+ SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x32, index, NULL, 0, 1000);
+ if (result < 0)
+ goto error;
+ msleep(5);
+
+ result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
+ SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x72, offset, NULL, 0, 1000);
+ if (result < 0)
+ goto error;
+ msleep(5);
+
+ result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
+ SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0xb2, value, NULL, 0, 1000);
+ if (result < 0)
+ goto error;
+ msleep(5);
+
+error:
+ return result;
+}
+
+static int sur40_set_preprocessor(struct sur40_state *dev, u8 value)
+{
+ u8 setting_07[2] = { 0x01, 0x00 };
+ u8 setting_17[2] = { 0x85, 0x80 };
+ int result;
+
+ if (value > 1)
+ return -ERANGE;
+
+ result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
+ SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x07, setting_07[value], NULL, 0, 1000);
+ if (result < 0)
+ goto error;
+ msleep(5);
+
+ result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
+ SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+ 0x17, setting_17[value], NULL, 0, 1000);
+ if (result < 0)
+ goto error;
+ msleep(5);
+
+error:
+ return result;
+}
+
+static void sur40_set_vsvideo(struct sur40_state *handle, u8 value)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ sur40_poke(handle, 0x1c+i, value);
+ handle->vsvideo = value;
+}
+
+static void sur40_set_irlevel(struct sur40_state *handle, u8 value)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ sur40_poke(handle, 0x08+(2*i), value);
+}
+
/* Initialization routine, called from sur40_open */
static int sur40_init(struct sur40_state *dev)
{
@@ -631,6 +751,36 @@ static int sur40_probe(struct usb_interface *interface,
sur40->vdev.queue = &sur40->queue;
video_set_drvdata(&sur40->vdev, sur40);
+ /* initialize the control handler for 4 controls */
+ v4l2_ctrl_handler_init(&sur40->hdl, 4);
+ sur40->v4l2.ctrl_handler = &sur40->hdl;
+ sur40->vsvideo = (SUR40_CONTRAST_DEF << 4) | SUR40_GAIN_DEF;
+
+ v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_BRIGHTNESS,
+ SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX, 1, clamp(brightness,
+ (uint)SUR40_BRIGHTNESS_MIN, (uint)SUR40_BRIGHTNESS_MAX));
+
+ v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_CONTRAST,
+ SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX, 1, clamp(contrast,
+ (uint)SUR40_CONTRAST_MIN, (uint)SUR40_CONTRAST_MAX));
+
+ v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_GAIN,
+ SUR40_GAIN_MIN, SUR40_GAIN_MAX, 1, clamp(gain,
+ (uint)SUR40_GAIN_MIN, (uint)SUR40_GAIN_MAX));
+
+ v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops,
+ V4L2_CID_BACKLIGHT_COMPENSATION, SUR40_BACKLIGHT_MIN,
+ SUR40_BACKLIGHT_MAX, 1, SUR40_BACKLIGHT_DEF);
+
+ v4l2_ctrl_handler_setup(&sur40->hdl);
+
+ if (sur40->hdl.error) {
+ dev_err(&interface->dev,
+ "Unable to register video controls.");
+ v4l2_ctrl_handler_free(&sur40->hdl);
+ goto err_unreg_v4l2;
+ }
+
error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
if (error) {
dev_err(&interface->dev,
@@ -663,6 +813,7 @@ static void sur40_disconnect(struct usb_interface *interface)
{
struct sur40_state *sur40 = usb_get_intfdata(interface);
+ v4l2_ctrl_handler_free(&sur40->hdl);
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
@@ -856,6 +1007,31 @@ static int sur40_vidioc_g_fmt(struct file *file, void *priv,
return 0;
}
+static int sur40_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct sur40_state *sur40 = container_of(ctrl->handler,
+ struct sur40_state, hdl);
+ u8 value = sur40->vsvideo;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ sur40_set_irlevel(sur40, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ value = (value & 0x0f) | (ctrl->val << 4);
+ sur40_set_vsvideo(sur40, value);
+ break;
+ case V4L2_CID_GAIN:
+ value = (value & 0xf0) | (ctrl->val);
+ sur40_set_vsvideo(sur40, value);
+ break;
+ case V4L2_CID_BACKLIGHT_COMPENSATION:
+ sur40_set_preprocessor(sur40, ctrl->val);
+ break;
+ }
+ return 0;
+}
+
static int sur40_ioctl_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{