Commit e0fbd25b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 "Mostly existing driver fixes plus a new driver for game controllers
  directly connected to Nintendo 64, and an enhancement for keyboards
  driven by Chrome OS EC to communicate layout of the top row to
  userspace"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (47 commits)
  Input: st1232 - fix NORMAL vs. IDLE state handling
  Input: aiptek - convert sysfs sprintf/snprintf family to sysfs_emit
  Input: alps - fix spelling of "positive"
  ARM: dts: cros-ec-keyboard: Use keymap macros
  dt-bindings: input: Fix the keymap for LOCK key
  dt-bindings: input: Create macros for cros-ec keymap
  Input: cros-ec-keyb - expose function row physical map to userspace
  dt-bindings: input: cros-ec-keyb: Add a new property describing top row
  Input: applespi - fix occasional crc errors under load.
  Input: applespi - don't wait for responses to commands indefinitely.
  Input: st1232 - add IDLE state as ready condition
  Input: zinitix - fix return type of zinitix_init_touch()
  Input: i8042 - add ASUS Zenbook Flip to noselftest list
  Input: add missing dependencies on CONFIG_HAS_IOMEM
  Input: joydev - prevent potential read overflow in ioctl
  Input: elo - fix an error code in elo_connect()
  Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox Series X|S
  Input: sur40 - fix an error code in sur40_probe()
  Input: elants_i2c - detect enum overflow
  Input: zinitix - remove unneeded semicolon
  ...
parents 69aea9d2 1bff77f4
What: /sys/class/input/input(x)/device/function_row_physmap
Date: January 2021
Contact: Philip Chen <philipchen@chromium.org>
Description: A space separated list of scancodes for the top row keys,
ordered by the physical positions of the keys, from left
to right.
...@@ -31,6 +31,17 @@ properties: ...@@ -31,6 +31,17 @@ properties:
if the EC does not have its own logic or hardware for this. if the EC does not have its own logic or hardware for this.
type: boolean type: boolean
function-row-physmap:
minItems: 1
maxItems: 15
description: |
An ordered u32 array describing the rows/columns (in the scan matrix)
of top row keys from physical left (KEY_F1) to right. Each entry
encodes the row/column as:
(((row) & 0xFF) << 24) | (((column) & 0xFF) << 16)
where the lower 16 bits are reserved. This property is specified only
when the keyboard has a custom design for the top row keys.
required: required:
- compatible - compatible
...@@ -38,11 +49,24 @@ unevaluatedProperties: false ...@@ -38,11 +49,24 @@ unevaluatedProperties: false
examples: examples:
- | - |
#include <dt-bindings/input/input.h>
cros-ec-keyb { cros-ec-keyb {
compatible = "google,cros-ec-keyb"; compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>; keypad,num-rows = <8>;
keypad,num-columns = <13>; keypad,num-columns = <13>;
google,needs-ghost-filter; google,needs-ghost-filter;
function-row-physmap = <
MATRIX_KEY(0x00, 0x02, 0) /* T1 */
MATRIX_KEY(0x03, 0x02, 0) /* T2 */
MATRIX_KEY(0x02, 0x02, 0) /* T3 */
MATRIX_KEY(0x01, 0x02, 0) /* T4 */
MATRIX_KEY(0x03, 0x04, 0) /* T5 */
MATRIX_KEY(0x02, 0x04, 0) /* T6 */
MATRIX_KEY(0x01, 0x04, 0) /* T7 */
MATRIX_KEY(0x02, 0x09, 0) /* T8 */
MATRIX_KEY(0x01, 0x09, 0) /* T9 */
MATRIX_KEY(0x00, 0x04, 0) /* T10 */
>;
/* /*
* Keymap entries take the form of 0xRRCCKKKK where * Keymap entries take the form of 0xRRCCKKKK where
* RR=Row CC=Column KKKK=Key Code * RR=Row CC=Column KKKK=Key Code
......
...@@ -6,103 +6,18 @@ ...@@ -6,103 +6,18 @@
*/ */
#include <dt-bindings/input/input.h> #include <dt-bindings/input/input.h>
#include <dt-bindings/input/cros-ec-keyboard.h>
&cros_ec { &cros_ec {
keyboard-controller { keyboard_controller: keyboard-controller {
compatible = "google,cros-ec-keyb"; compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>; keypad,num-rows = <8>;
keypad,num-columns = <13>; keypad,num-columns = <13>;
google,needs-ghost-filter; google,needs-ghost-filter;
linux,keymap = < linux,keymap = <
MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA) CROS_STD_TOP_ROW_KEYMAP
MATRIX_KEY(0x00, 0x02, KEY_F1) CROS_STD_MAIN_KEYMAP
MATRIX_KEY(0x00, 0x03, KEY_B)
MATRIX_KEY(0x00, 0x04, KEY_F10)
MATRIX_KEY(0x00, 0x05, KEY_RO)
MATRIX_KEY(0x00, 0x06, KEY_N)
MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
MATRIX_KEY(0x01, 0x01, KEY_ESC)
MATRIX_KEY(0x01, 0x02, KEY_F4)
MATRIX_KEY(0x01, 0x03, KEY_G)
MATRIX_KEY(0x01, 0x04, KEY_F7)
MATRIX_KEY(0x01, 0x06, KEY_H)
MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
MATRIX_KEY(0x01, 0x09, KEY_F9)
MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
MATRIX_KEY(0x01, 0x0c, KEY_HENKAN)
MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
MATRIX_KEY(0x02, 0x01, KEY_TAB)
MATRIX_KEY(0x02, 0x02, KEY_F3)
MATRIX_KEY(0x02, 0x03, KEY_T)
MATRIX_KEY(0x02, 0x04, KEY_F6)
MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE)
MATRIX_KEY(0x02, 0x06, KEY_Y)
MATRIX_KEY(0x02, 0x07, KEY_102ND)
MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
MATRIX_KEY(0x02, 0x09, KEY_F8)
MATRIX_KEY(0x02, 0x0a, KEY_YEN)
MATRIX_KEY(0x03, 0x00, KEY_LEFTMETA)
MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
MATRIX_KEY(0x03, 0x02, KEY_F2)
MATRIX_KEY(0x03, 0x03, KEY_5)
MATRIX_KEY(0x03, 0x04, KEY_F5)
MATRIX_KEY(0x03, 0x06, KEY_6)
MATRIX_KEY(0x03, 0x08, KEY_MINUS)
MATRIX_KEY(0x03, 0x09, KEY_F13)
MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN)
MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
MATRIX_KEY(0x04, 0x01, KEY_A)
MATRIX_KEY(0x04, 0x02, KEY_D)
MATRIX_KEY(0x04, 0x03, KEY_F)
MATRIX_KEY(0x04, 0x04, KEY_S)
MATRIX_KEY(0x04, 0x05, KEY_K)
MATRIX_KEY(0x04, 0x06, KEY_J)
MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON)
MATRIX_KEY(0x04, 0x09, KEY_L)
MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH)
MATRIX_KEY(0x04, 0x0b, KEY_ENTER)
MATRIX_KEY(0x05, 0x01, KEY_Z)
MATRIX_KEY(0x05, 0x02, KEY_C)
MATRIX_KEY(0x05, 0x03, KEY_V)
MATRIX_KEY(0x05, 0x04, KEY_X)
MATRIX_KEY(0x05, 0x05, KEY_COMMA)
MATRIX_KEY(0x05, 0x06, KEY_M)
MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT)
MATRIX_KEY(0x05, 0x08, KEY_SLASH)
MATRIX_KEY(0x05, 0x09, KEY_DOT)
MATRIX_KEY(0x05, 0x0b, KEY_SPACE)
MATRIX_KEY(0x06, 0x01, KEY_1)
MATRIX_KEY(0x06, 0x02, KEY_3)
MATRIX_KEY(0x06, 0x03, KEY_4)
MATRIX_KEY(0x06, 0x04, KEY_2)
MATRIX_KEY(0x06, 0x05, KEY_8)
MATRIX_KEY(0x06, 0x06, KEY_7)
MATRIX_KEY(0x06, 0x08, KEY_0)
MATRIX_KEY(0x06, 0x09, KEY_9)
MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT)
MATRIX_KEY(0x06, 0x0b, KEY_DOWN)
MATRIX_KEY(0x06, 0x0c, KEY_RIGHT)
MATRIX_KEY(0x07, 0x01, KEY_Q)
MATRIX_KEY(0x07, 0x02, KEY_E)
MATRIX_KEY(0x07, 0x03, KEY_R)
MATRIX_KEY(0x07, 0x04, KEY_W)
MATRIX_KEY(0x07, 0x05, KEY_I)
MATRIX_KEY(0x07, 0x06, KEY_U)
MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT)
MATRIX_KEY(0x07, 0x08, KEY_P)
MATRIX_KEY(0x07, 0x09, KEY_O)
MATRIX_KEY(0x07, 0x0b, KEY_UP)
MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
>; >;
}; };
}; };
...@@ -456,7 +456,7 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, ...@@ -456,7 +456,7 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
if (IS_ERR(abspam)) if (IS_ERR(abspam))
return PTR_ERR(abspam); return PTR_ERR(abspam);
for (i = 0; i < joydev->nabs; i++) { for (i = 0; i < len && i < joydev->nabs; i++) {
if (abspam[i] > ABS_MAX) { if (abspam[i] > ABS_MAX) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
...@@ -480,6 +480,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, ...@@ -480,6 +480,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
int i; int i;
int retval = 0; int retval = 0;
if (len % sizeof(*keypam))
return -EINVAL;
len = min(len, sizeof(joydev->keypam)); len = min(len, sizeof(joydev->keypam));
/* Validate the map. */ /* Validate the map. */
...@@ -487,7 +490,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, ...@@ -487,7 +490,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
if (IS_ERR(keypam)) if (IS_ERR(keypam))
return PTR_ERR(keypam); return PTR_ERR(keypam);
for (i = 0; i < joydev->nkey; i++) { for (i = 0; i < (len / 2) && i < joydev->nkey; i++) {
if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
......
...@@ -382,4 +382,11 @@ config JOYSTICK_FSIA6B ...@@ -382,4 +382,11 @@ config JOYSTICK_FSIA6B
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called fsia6b. module will be called fsia6b.
config JOYSTICK_N64
bool "N64 controller"
depends on MACH_NINTENDO64
help
Say Y here if you want enable support for the four
built-in controller ports on the Nintendo 64 console.
endif endif
...@@ -24,6 +24,7 @@ obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o ...@@ -24,6 +24,7 @@ obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
...@@ -37,4 +38,3 @@ obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o ...@@ -37,4 +38,3 @@ obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
// SPDX-License-Identifier: GPL-2.0
/*
* Support for the four N64 controllers.
*
* Copyright (c) 2021 Lauri Kasanen
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/limits.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/timer.h>
MODULE_AUTHOR("Lauri Kasanen <cand@gmx.com>");
MODULE_DESCRIPTION("Driver for N64 controllers");
MODULE_LICENSE("GPL");
#define PIF_RAM 0x1fc007c0
#define SI_DRAM_REG 0
#define SI_READ_REG 1
#define SI_WRITE_REG 4
#define SI_STATUS_REG 6
#define SI_STATUS_DMA_BUSY BIT(0)
#define SI_STATUS_IO_BUSY BIT(1)
#define N64_CONTROLLER_ID 0x0500
#define MAX_CONTROLLERS 4
static const char *n64joy_phys[MAX_CONTROLLERS] = {
"n64joy/port0",
"n64joy/port1",
"n64joy/port2",
"n64joy/port3",
};
struct n64joy_priv {
u64 si_buf[8] ____cacheline_aligned;
struct timer_list timer;
struct mutex n64joy_mutex;
struct input_dev *n64joy_dev[MAX_CONTROLLERS];
u32 __iomem *reg_base;
u8 n64joy_opened;
};
struct joydata {
unsigned int: 16; /* unused */
unsigned int err: 2;
unsigned int: 14; /* unused */
union {
u32 data;
struct {
unsigned int a: 1;
unsigned int b: 1;
unsigned int z: 1;
unsigned int start: 1;
unsigned int up: 1;
unsigned int down: 1;
unsigned int left: 1;
unsigned int right: 1;
unsigned int: 2; /* unused */
unsigned int l: 1;
unsigned int r: 1;
unsigned int c_up: 1;
unsigned int c_down: 1;
unsigned int c_left: 1;
unsigned int c_right: 1;
signed int x: 8;
signed int y: 8;
};
};
};
static void n64joy_write_reg(u32 __iomem *reg_base, const u8 reg, const u32 value)
{
writel(value, reg_base + reg);
}
static u32 n64joy_read_reg(u32 __iomem *reg_base, const u8 reg)
{
return readl(reg_base + reg);
}
static void n64joy_wait_si_dma(u32 __iomem *reg_base)
{
while (n64joy_read_reg(reg_base, SI_STATUS_REG) &
(SI_STATUS_DMA_BUSY | SI_STATUS_IO_BUSY))
cpu_relax();
}
static void n64joy_exec_pif(struct n64joy_priv *priv, const u64 in[8])
{
unsigned long flags;
dma_cache_wback_inv((unsigned long) in, 8 * 8);
dma_cache_inv((unsigned long) priv->si_buf, 8 * 8);
local_irq_save(flags);
n64joy_wait_si_dma(priv->reg_base);
barrier();
n64joy_write_reg(priv->reg_base, SI_DRAM_REG, virt_to_phys(in));
barrier();
n64joy_write_reg(priv->reg_base, SI_WRITE_REG, PIF_RAM);
barrier();
n64joy_wait_si_dma(priv->reg_base);
barrier();
n64joy_write_reg(priv->reg_base, SI_DRAM_REG, virt_to_phys(priv->si_buf));
barrier();
n64joy_write_reg(priv->reg_base, SI_READ_REG, PIF_RAM);
barrier();
n64joy_wait_si_dma(priv->reg_base);
local_irq_restore(flags);
}
static const u64 polldata[] ____cacheline_aligned = {
0xff010401ffffffff,
0xff010401ffffffff,
0xff010401ffffffff,
0xff010401ffffffff,
0xfe00000000000000,
0,
0,
1
};
static void n64joy_poll(struct timer_list *t)
{
const struct joydata *data;
struct n64joy_priv *priv = container_of(t, struct n64joy_priv, timer);
struct input_dev *dev;
u32 i;
n64joy_exec_pif(priv, polldata);
data = (struct joydata *) priv->si_buf;
for (i = 0; i < MAX_CONTROLLERS; i++) {
if (!priv->n64joy_dev[i])
continue;
dev = priv->n64joy_dev[i];
/* d-pad */
input_report_key(dev, BTN_DPAD_UP, data[i].up);
input_report_key(dev, BTN_DPAD_DOWN, data[i].down);
input_report_key(dev, BTN_DPAD_LEFT, data[i].left);
input_report_key(dev, BTN_DPAD_RIGHT, data[i].right);
/* c buttons */
input_report_key(dev, BTN_FORWARD, data[i].c_up);
input_report_key(dev, BTN_BACK, data[i].c_down);
input_report_key(dev, BTN_LEFT, data[i].c_left);
input_report_key(dev, BTN_RIGHT, data[i].c_right);
/* matching buttons */
input_report_key(dev, BTN_START, data[i].start);
input_report_key(dev, BTN_Z, data[i].z);
/* remaining ones: a, b, l, r */
input_report_key(dev, BTN_0, data[i].a);
input_report_key(dev, BTN_1, data[i].b);
input_report_key(dev, BTN_2, data[i].l);
input_report_key(dev, BTN_3, data[i].r);
input_report_abs(dev, ABS_X, data[i].x);
input_report_abs(dev, ABS_Y, data[i].y);
input_sync(dev);
}
mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
}
static int n64joy_open(struct input_dev *dev)
{
struct n64joy_priv *priv = input_get_drvdata(dev);
int err;
err = mutex_lock_interruptible(&priv->n64joy_mutex);
if (err)
return err;
if (!priv->n64joy_opened) {
/*
* We could use the vblank irq, but it's not important if
* the poll point slightly changes.
*/
timer_setup(&priv->timer, n64joy_poll, 0);
mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16));
}
priv->n64joy_opened++;
mutex_unlock(&priv->n64joy_mutex);
return err;
}
static void n64joy_close(struct input_dev *dev)
{
struct n64joy_priv *priv = input_get_drvdata(dev);
mutex_lock(&priv->n64joy_mutex);
if (!--priv->n64joy_opened)
del_timer_sync(&priv->timer);
mutex_unlock(&priv->n64joy_mutex);
}
static const u64 __initconst scandata[] ____cacheline_aligned = {
0xff010300ffffffff,
0xff010300ffffffff,
0xff010300ffffffff,
0xff010300ffffffff,
0xfe00000000000000,
0,
0,
1
};
/*
* The target device is embedded and RAM-constrained. We save RAM
* by initializing in __init code that gets dropped late in boot.
* For the same reason there is no module or unloading support.
*/
static int __init n64joy_probe(struct platform_device *pdev)
{
const struct joydata *data;
struct n64joy_priv *priv;
struct input_dev *dev;
int err = 0;
u32 i, j, found = 0;
priv = kzalloc(sizeof(struct n64joy_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
mutex_init(&priv->n64joy_mutex);
priv->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (!priv->reg_base) {
err = -EINVAL;
goto fail;
}
/* The controllers are not hotpluggable, so we can scan in init */
n64joy_exec_pif(priv, scandata);
data = (struct joydata *) priv->si_buf;
for (i = 0; i < MAX_CONTROLLERS; i++) {
if (!data[i].err && data[i].data >> 16 == N64_CONTROLLER_ID) {
found++;
dev = priv->n64joy_dev[i] = input_allocate_device();
if (!priv->n64joy_dev[i]) {
err = -ENOMEM;
goto fail;
}
input_set_drvdata(dev, priv);
dev->name = "N64 controller";
dev->phys = n64joy_phys[i];
dev->id.bustype = BUS_HOST;
dev->id.vendor = 0;
dev->id.product = data[i].data >> 16;
dev->id.version = 0;
dev->dev.parent = &pdev->dev;
dev->open = n64joy_open;
dev->close = n64joy_close;
/* d-pad */
input_set_capability(dev, EV_KEY, BTN_DPAD_UP);
input_set_capability(dev, EV_KEY, BTN_DPAD_DOWN);
input_set_capability(dev, EV_KEY, BTN_DPAD_LEFT);
input_set_capability(dev, EV_KEY, BTN_DPAD_RIGHT);
/* c buttons */
input_set_capability(dev, EV_KEY, BTN_LEFT);
input_set_capability(dev, EV_KEY, BTN_RIGHT);
input_set_capability(dev, EV_KEY, BTN_FORWARD);
input_set_capability(dev, EV_KEY, BTN_BACK);
/* matching buttons */
input_set_capability(dev, EV_KEY, BTN_START);
input_set_capability(dev, EV_KEY, BTN_Z);
/* remaining ones: a, b, l, r */
input_set_capability(dev, EV_KEY, BTN_0);
input_set_capability(dev, EV_KEY, BTN_1);
input_set_capability(dev, EV_KEY, BTN_2);
input_set_capability(dev, EV_KEY, BTN_3);
for (j = 0; j < 2; j++)
input_set_abs_params(dev, ABS_X + j,
S8_MIN, S8_MAX, 0, 0);
err = input_register_device(dev);
if (err) {
input_free_device(dev);
goto fail;
}
}
}
pr_info("%u controller(s) connected\n", found);
if (!found)
return -ENODEV;
return 0;
fail:
for (i = 0; i < MAX_CONTROLLERS; i++) {
if (!priv->n64joy_dev[i])
continue;
input_unregister_device(priv->n64joy_dev[i]);
}
return err;
}
static struct platform_driver n64joy_driver = {
.driver = {
.name = "n64joy",
},
};
static int __init n64joy_init(void)
{
return platform_driver_probe(&n64joy_driver, n64joy_probe);
}
module_init(n64joy_init);
...@@ -305,6 +305,7 @@ static const struct xpad_device { ...@@ -305,6 +305,7 @@ static const struct xpad_device {
{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE }, { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 }, { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
......
...@@ -446,7 +446,7 @@ config KEYBOARD_MPR121 ...@@ -446,7 +446,7 @@ config KEYBOARD_MPR121
config KEYBOARD_SNVS_PWRKEY config KEYBOARD_SNVS_PWRKEY
tristate "IMX SNVS Power Key Driver" tristate "IMX SNVS Power Key Driver"
depends on ARCH_MXC || COMPILE_TEST depends on ARCH_MXC || (COMPILE_TEST && HAS_IOMEM)
depends on OF depends on OF
help help
This is the snvs powerkey driver for the Freescale i.MX application This is the snvs powerkey driver for the Freescale i.MX application
...@@ -685,7 +685,7 @@ config KEYBOARD_OMAP ...@@ -685,7 +685,7 @@ config KEYBOARD_OMAP
config KEYBOARD_OMAP4 config KEYBOARD_OMAP4
tristate "TI OMAP4+ keypad support" tristate "TI OMAP4+ keypad support"
depends on OF || ARCH_OMAP2PLUS depends on (OF && HAS_IOMEM) || ARCH_OMAP2PLUS
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
help help
Say Y here if you want to use the OMAP4+ keypad. Say Y here if you want to use the OMAP4+ keypad.
...@@ -773,7 +773,7 @@ config KEYBOARD_CAP11XX ...@@ -773,7 +773,7 @@ config KEYBOARD_CAP11XX
config KEYBOARD_BCM config KEYBOARD_BCM
tristate "Broadcom keypad driver" tristate "Broadcom keypad driver"
depends on OF && HAVE_CLK depends on OF && HAVE_CLK && HAS_IOMEM
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
default ARCH_BCM_CYGNUS default ARCH_BCM_CYGNUS
help help
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/ktime.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -409,7 +410,7 @@ struct applespi_data { ...@@ -409,7 +410,7 @@ struct applespi_data {
unsigned int cmd_msg_cntr; unsigned int cmd_msg_cntr;
/* lock to protect the above parameters and flags below */ /* lock to protect the above parameters and flags below */
spinlock_t cmd_msg_lock; spinlock_t cmd_msg_lock;
bool cmd_msg_queued; ktime_t cmd_msg_queued;
enum applespi_evt_type cmd_evt_type; enum applespi_evt_type cmd_evt_type;
struct led_classdev backlight_info; struct led_classdev backlight_info;
...@@ -729,7 +730,7 @@ static void applespi_msg_complete(struct applespi_data *applespi, ...@@ -729,7 +730,7 @@ static void applespi_msg_complete(struct applespi_data *applespi,
wake_up_all(&applespi->drain_complete); wake_up_all(&applespi->drain_complete);
if (is_write_msg) { if (is_write_msg) {
applespi->cmd_msg_queued = false; applespi->cmd_msg_queued = 0;
applespi_send_cmd_msg(applespi); applespi_send_cmd_msg(applespi);
} }
...@@ -748,6 +749,8 @@ static void applespi_async_write_complete(void *context) ...@@ -748,6 +749,8 @@ static void applespi_async_write_complete(void *context)
applespi->tx_status, applespi->tx_status,
APPLESPI_STATUS_SIZE); APPLESPI_STATUS_SIZE);
udelay(SPI_RW_CHG_DELAY_US);
if (!applespi_check_write_status(applespi, applespi->wr_m.status)) { if (!applespi_check_write_status(applespi, applespi->wr_m.status)) {
/* /*
* If we got an error, we presumably won't get the expected * If we got an error, we presumably won't get the expected
...@@ -771,9 +774,17 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi) ...@@ -771,9 +774,17 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)
return 0; return 0;
/* check whether send is in progress */ /* check whether send is in progress */
if (applespi->cmd_msg_queued) if (applespi->cmd_msg_queued) {
if (ktime_ms_delta(ktime_get(), applespi->cmd_msg_queued) < 1000)
return 0; return 0;
dev_warn(&applespi->spi->dev, "Command %d timed out\n",
applespi->cmd_evt_type);
applespi->cmd_msg_queued = 0;
applespi->write_active = false;
}
/* set up packet */ /* set up packet */
memset(packet, 0, APPLESPI_PACKET_SIZE); memset(packet, 0, APPLESPI_PACKET_SIZE);
...@@ -869,7 +880,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi) ...@@ -869,7 +880,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)
return sts; return sts;
} }
applespi->cmd_msg_queued = true; applespi->cmd_msg_queued = ktime_get_coarse();
applespi->write_active = true; applespi->write_active = true;
return 0; return 0;
...@@ -1921,7 +1932,7 @@ static int __maybe_unused applespi_resume(struct device *dev) ...@@ -1921,7 +1932,7 @@ static int __maybe_unused applespi_resume(struct device *dev)
applespi->drain = false; applespi->drain = false;
applespi->have_cl_led_on = false; applespi->have_cl_led_on = false;
applespi->have_bl_level = 0; applespi->have_bl_level = 0;
applespi->cmd_msg_queued = false; applespi->cmd_msg_queued = 0;
applespi->read_active = false; applespi->read_active = false;
applespi->write_active = false; applespi->write_active = false;
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#define MAX_NUM_TOP_ROW_KEYS 15
/** /**
* struct cros_ec_keyb - Structure representing EC keyboard device * struct cros_ec_keyb - Structure representing EC keyboard device
* *
...@@ -42,6 +44,9 @@ ...@@ -42,6 +44,9 @@
* @idev: The input device for the matrix keys. * @idev: The input device for the matrix keys.
* @bs_idev: The input device for non-matrix buttons and switches (or NULL). * @bs_idev: The input device for non-matrix buttons and switches (or NULL).
* @notifier: interrupt event notifier for transport devices * @notifier: interrupt event notifier for transport devices
* @function_row_physmap: An array of the encoded rows/columns for the top
* row function keys, in an order from left to right
* @num_function_row_keys: The number of top row keys in a custom keyboard
*/ */
struct cros_ec_keyb { struct cros_ec_keyb {
unsigned int rows; unsigned int rows;
...@@ -58,6 +63,9 @@ struct cros_ec_keyb { ...@@ -58,6 +63,9 @@ struct cros_ec_keyb {
struct input_dev *idev; struct input_dev *idev;
struct input_dev *bs_idev; struct input_dev *bs_idev;
struct notifier_block notifier; struct notifier_block notifier;
u16 function_row_physmap[MAX_NUM_TOP_ROW_KEYS];
size_t num_function_row_keys;
}; };
/** /**
...@@ -527,6 +535,11 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) ...@@ -527,6 +535,11 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
struct input_dev *idev; struct input_dev *idev;
const char *phys; const char *phys;
int err; int err;
struct property *prop;
const __be32 *p;
u16 *physmap;
u32 key_pos;
int row, col;
err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols); err = matrix_keypad_parse_properties(dev, &ckdev->rows, &ckdev->cols);
if (err) if (err)
...@@ -578,6 +591,21 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) ...@@ -578,6 +591,21 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
ckdev->idev = idev; ckdev->idev = idev;
cros_ec_keyb_compute_valid_keys(ckdev); cros_ec_keyb_compute_valid_keys(ckdev);
physmap = ckdev->function_row_physmap;
of_property_for_each_u32(dev->of_node, "function-row-physmap",
prop, p, key_pos) {
if (ckdev->num_function_row_keys == MAX_NUM_TOP_ROW_KEYS) {
dev_warn(dev, "Only support up to %d top row keys\n",
MAX_NUM_TOP_ROW_KEYS);
break;
}
row = KEY_ROW(key_pos);
col = KEY_COL(key_pos);
*physmap = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
physmap++;
ckdev->num_function_row_keys++;
}
err = input_register_device(ckdev->idev); err = input_register_device(ckdev->idev);
if (err) { if (err) {
dev_err(dev, "cannot register input device\n"); dev_err(dev, "cannot register input device\n");
...@@ -587,6 +615,51 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev) ...@@ -587,6 +615,51 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
return 0; return 0;
} }
static ssize_t function_row_physmap_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
ssize_t size = 0;
int i;
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
u16 *physmap = ckdev->function_row_physmap;
for (i = 0; i < ckdev->num_function_row_keys; i++)
size += scnprintf(buf + size, PAGE_SIZE - size,
"%s%02X", size ? " " : "", physmap[i]);
if (size)
size += scnprintf(buf + size, PAGE_SIZE - size, "\n");
return size;
}
static DEVICE_ATTR_RO(function_row_physmap);
static struct attribute *cros_ec_keyb_attrs[] = {
&dev_attr_function_row_physmap.attr,
NULL,
};
static umode_t cros_ec_keyb_attr_is_visible(struct kobject *kobj,
struct attribute *attr,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
if (attr == &dev_attr_function_row_physmap.attr &&
!ckdev->num_function_row_keys)
return 0;
return attr->mode;
}
static const struct attribute_group cros_ec_keyb_attr_group = {
.is_visible = cros_ec_keyb_attr_is_visible,
.attrs = cros_ec_keyb_attrs,
};
static int cros_ec_keyb_probe(struct platform_device *pdev) static int cros_ec_keyb_probe(struct platform_device *pdev)
{ {
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
...@@ -617,6 +690,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) ...@@ -617,6 +690,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
return err; return err;
} }
err = devm_device_add_group(dev, &cros_ec_keyb_attr_group);
if (err) {
dev_err(dev, "failed to create attributes. err=%d\n", err);
return err;
}
ckdev->notifier.notifier_call = cros_ec_keyb_work; ckdev->notifier.notifier_call = cros_ec_keyb_work;
err = blocking_notifier_chain_register(&ckdev->ec->event_notifier, err = blocking_notifier_chain_register(&ckdev->ec->event_notifier,
&ckdev->notifier); &ckdev->notifier);
......
This diff is collapsed.
...@@ -863,6 +863,7 @@ static void da7280_parse_properties(struct device *dev, ...@@ -863,6 +863,7 @@ static void da7280_parse_properties(struct device *dev,
gpi_str3[7] = '0' + i; gpi_str3[7] = '0' + i;
haptics->gpi_ctl[i].polarity = 0; haptics->gpi_ctl[i].polarity = 0;
error = device_property_read_string(dev, gpi_str3, &str); error = device_property_read_string(dev, gpi_str3, &str);
if (!error)
haptics->gpi_ctl[i].polarity = haptics->gpi_ctl[i].polarity =
da7280_haptic_of_gpi_pol_str(dev, str); da7280_haptic_of_gpi_pol_str(dev, str);
} }
...@@ -1299,11 +1300,13 @@ static int __maybe_unused da7280_resume(struct device *dev) ...@@ -1299,11 +1300,13 @@ static int __maybe_unused da7280_resume(struct device *dev)
return retval; return retval;
} }
#ifdef CONFIG_OF
static const struct of_device_id da7280_of_match[] = { static const struct of_device_id da7280_of_match[] = {
{ .compatible = "dlg,da7280", }, { .compatible = "dlg,da7280", },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, da7280_of_match); MODULE_DEVICE_TABLE(of, da7280_of_match);
#endif
static const struct i2c_device_id da7280_i2c_id[] = { static const struct i2c_device_id da7280_i2c_id[] = {
{ "da7280", }, { "da7280", },
......
...@@ -986,7 +986,7 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt, ...@@ -986,7 +986,7 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
case V7_PACKET_ID_TWO: case V7_PACKET_ID_TWO:
mt[1].x &= ~0x000F; mt[1].x &= ~0x000F;
mt[1].y |= 0x000F; mt[1].y |= 0x000F;
/* Detect false-postive touches where x & y report max value */ /* Detect false-positive touches where x & y report max value */
if (mt[1].y == 0x7ff && mt[1].x == 0xff0) { if (mt[1].y == 0x7ff && mt[1].x == 0xff0) {
mt[1].x = 0; mt[1].x = 0;
/* y gets set to 0 at the end of this function */ /* y gets set to 0 at the end of this function */
......
...@@ -1106,8 +1106,11 @@ static void synaptics_process_packet(struct psmouse *psmouse) ...@@ -1106,8 +1106,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
num_fingers = hw.w + 2; num_fingers = hw.w + 2;
break; break;
case 2: case 2:
if (SYN_MODEL_PEN(info->model_id)) /*
; /* Nothing, treat a pen as a single finger */ * SYN_MODEL_PEN(info->model_id): even if
* the device supports pen, we treat it as
* a single finger.
*/
break; break;
case 4 ... 15: case 4 ... 15:
if (SYN_CAP_PALMDETECT(info->capabilities)) if (SYN_CAP_PALMDETECT(info->capabilities))
......
...@@ -255,7 +255,7 @@ config SERIO_ARC_PS2 ...@@ -255,7 +255,7 @@ config SERIO_ARC_PS2
config SERIO_APBPS2 config SERIO_APBPS2
tristate "GRLIB APBPS2 PS/2 keyboard/mouse controller" tristate "GRLIB APBPS2 PS/2 keyboard/mouse controller"
depends on OF depends on OF && HAS_IOMEM
help help
Say Y here if you want support for GRLIB APBPS2 peripherals used Say Y here if you want support for GRLIB APBPS2 peripherals used
to connect to PS/2 keyboard and/or mouse. to connect to PS/2 keyboard and/or mouse.
......
...@@ -588,6 +588,10 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = { ...@@ -588,6 +588,10 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
}, },
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
},
}, },
{ } { }
}; };
......
...@@ -1036,7 +1036,7 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr ...@@ -1036,7 +1036,7 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%dx%d\n", return sysfs_emit(buf, "%dx%d\n",
input_abs_get_max(aiptek->inputdev, ABS_X) + 1, input_abs_get_max(aiptek->inputdev, ABS_X) + 1,
input_abs_get_max(aiptek->inputdev, ABS_Y) + 1); input_abs_get_max(aiptek->inputdev, ABS_Y) + 1);
} }
...@@ -1064,8 +1064,7 @@ static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribut ...@@ -1064,8 +1064,7 @@ static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribut
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(pointer_mode_map,
map_val_to_str(pointer_mode_map,
aiptek->curSetting.pointerMode)); aiptek->curSetting.pointerMode));
} }
...@@ -1101,8 +1100,7 @@ static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attri ...@@ -1101,8 +1100,7 @@ static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attri
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(coordinate_mode_map,
map_val_to_str(coordinate_mode_map,
aiptek->curSetting.coordinateMode)); aiptek->curSetting.coordinateMode));
} }
...@@ -1143,8 +1141,7 @@ static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute * ...@@ -1143,8 +1141,7 @@ static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(tool_mode_map,
map_val_to_str(tool_mode_map,
aiptek->curSetting.toolMode)); aiptek->curSetting.toolMode));
} }
...@@ -1174,10 +1171,9 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att ...@@ -1174,10 +1171,9 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) { if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n"); return sysfs_emit(buf, "disable\n");
} else { } else {
return snprintf(buf, PAGE_SIZE, "%d\n", return sysfs_emit(buf, "%d\n", aiptek->curSetting.xTilt);
aiptek->curSetting.xTilt);
} }
} }
...@@ -1216,10 +1212,9 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att ...@@ -1216,10 +1212,9 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) { if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n"); return sysfs_emit(buf, "disable\n");
} else { } else {
return snprintf(buf, PAGE_SIZE, "%d\n", return sysfs_emit(buf, "%d\n", aiptek->curSetting.yTilt);
aiptek->curSetting.yTilt);
} }
} }
...@@ -1257,7 +1252,7 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut ...@@ -1257,7 +1252,7 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay); return sysfs_emit(buf, "%d\n", aiptek->curSetting.jitterDelay);
} }
static ssize_t static ssize_t
...@@ -1286,8 +1281,7 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at ...@@ -1286,8 +1281,7 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", return sysfs_emit(buf, "%d\n", aiptek->curSetting.programmableDelay);
aiptek->curSetting.programmableDelay);
} }
static ssize_t static ssize_t
...@@ -1316,7 +1310,7 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri ...@@ -1316,7 +1310,7 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount); return sysfs_emit(buf, "%ld\n", aiptek->eventCount);
} }
static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL); static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL);
...@@ -1355,7 +1349,7 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at ...@@ -1355,7 +1349,7 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at
default: default:
return 0; return 0;
} }
return snprintf(buf, PAGE_SIZE, retMsg); return sysfs_emit(buf, retMsg);
} }
static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL); static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
...@@ -1375,8 +1369,7 @@ static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribut ...@@ -1375,8 +1369,7 @@ static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribut
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(stylus_button_map,
map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonUpper)); aiptek->curSetting.stylusButtonUpper));
} }
...@@ -1406,8 +1399,7 @@ static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribut ...@@ -1406,8 +1399,7 @@ static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribut
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(stylus_button_map,
map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonLower)); aiptek->curSetting.stylusButtonLower));
} }
...@@ -1444,8 +1436,7 @@ static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute ...@@ -1444,8 +1436,7 @@ static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonLeft)); aiptek->curSetting.mouseButtonLeft));
} }
...@@ -1474,8 +1465,7 @@ static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribut ...@@ -1474,8 +1465,7 @@ static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribut
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonMiddle)); aiptek->curSetting.mouseButtonMiddle));
} }
...@@ -1504,8 +1494,7 @@ static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute ...@@ -1504,8 +1494,7 @@ static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n", return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonRight)); aiptek->curSetting.mouseButtonRight));
} }
...@@ -1535,10 +1524,9 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att ...@@ -1535,10 +1524,9 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) { if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n"); return sysfs_emit(buf, "disable\n");
} else { } else {
return snprintf(buf, PAGE_SIZE, "%d\n", return sysfs_emit(buf, "%d\n", aiptek->curSetting.wheel);
aiptek->curSetting.wheel);
} }
} }
...@@ -1568,8 +1556,7 @@ static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *a ...@@ -1568,8 +1556,7 @@ static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *a
/* There is nothing useful to display, so a one-line manual /* There is nothing useful to display, so a one-line manual
* is in order... * is in order...
*/ */
return snprintf(buf, PAGE_SIZE, return sysfs_emit(buf, "Write anything to this file to program your tablet.\n");
"Write anything to this file to program your tablet.\n");
} }
static ssize_t static ssize_t
...@@ -1600,7 +1587,7 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a ...@@ -1600,7 +1587,7 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode); return sysfs_emit(buf, "0x%04x\n", aiptek->features.odmCode);
} }
static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL); static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL);
...@@ -1613,7 +1600,7 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute ...@@ -1613,7 +1600,7 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode); return sysfs_emit(buf, "0x%04x\n", aiptek->features.modelCode);
} }
static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL); static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL);
...@@ -1626,8 +1613,7 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at ...@@ -1626,8 +1613,7 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
{ {
struct aiptek *aiptek = dev_get_drvdata(dev); struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%04x\n", return sysfs_emit(buf, "%04x\n", aiptek->features.firmwareCode);
aiptek->features.firmwareCode);
} }
static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL); static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
......
...@@ -608,7 +608,7 @@ config TOUCHSCREEN_MTOUCH ...@@ -608,7 +608,7 @@ config TOUCHSCREEN_MTOUCH
config TOUCHSCREEN_IMX6UL_TSC config TOUCHSCREEN_IMX6UL_TSC
tristate "Freescale i.MX6UL touchscreen controller" tristate "Freescale i.MX6UL touchscreen controller"
depends on (OF && GPIOLIB) || COMPILE_TEST depends on ((OF && GPIOLIB) || COMPILE_TEST) && HAS_IOMEM
help help
Say Y here if you have a Freescale i.MX6UL, and want to Say Y here if you have a Freescale i.MX6UL, and want to
use the internal touchscreen controller. use the internal touchscreen controller.
......
This diff is collapsed.
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#define QUEUE_HEADER_SINGLE 0x62 #define QUEUE_HEADER_SINGLE 0x62
#define QUEUE_HEADER_NORMAL 0X63 #define QUEUE_HEADER_NORMAL 0X63
#define QUEUE_HEADER_WAIT 0x64 #define QUEUE_HEADER_WAIT 0x64
#define QUEUE_HEADER_NORMAL2 0x66
/* Command header definition */ /* Command header definition */
#define CMD_HEADER_WRITE 0x54 #define CMD_HEADER_WRITE 0x54
...@@ -69,6 +70,7 @@ ...@@ -69,6 +70,7 @@
#define CMD_HEADER_REK 0x66 #define CMD_HEADER_REK 0x66
/* FW position data */ /* FW position data */
#define PACKET_SIZE_OLD 40
#define PACKET_SIZE 55 #define PACKET_SIZE 55
#define MAX_CONTACT_NUM 10 #define MAX_CONTACT_NUM 10
#define FW_POS_HEADER 0 #define FW_POS_HEADER 0
...@@ -90,6 +92,8 @@ ...@@ -90,6 +92,8 @@
/* FW read command, 0x53 0x?? 0x0, 0x01 */ /* FW read command, 0x53 0x?? 0x0, 0x01 */
#define E_ELAN_INFO_FW_VER 0x00 #define E_ELAN_INFO_FW_VER 0x00
#define E_ELAN_INFO_BC_VER 0x10 #define E_ELAN_INFO_BC_VER 0x10
#define E_ELAN_INFO_X_RES 0x60
#define E_ELAN_INFO_Y_RES 0x63
#define E_ELAN_INFO_REK 0xD0 #define E_ELAN_INFO_REK 0xD0
#define E_ELAN_INFO_TEST_VER 0xE0 #define E_ELAN_INFO_TEST_VER 0xE0
#define E_ELAN_INFO_FW_ID 0xF0 #define E_ELAN_INFO_FW_ID 0xF0
...@@ -112,6 +116,11 @@ ...@@ -112,6 +116,11 @@
#define ELAN_POWERON_DELAY_USEC 500 #define ELAN_POWERON_DELAY_USEC 500
#define ELAN_RESET_DELAY_MSEC 20 #define ELAN_RESET_DELAY_MSEC 20
enum elants_chip_id {
EKTH3500,
EKTF3624,
};
enum elants_state { enum elants_state {
ELAN_STATE_NORMAL, ELAN_STATE_NORMAL,
ELAN_WAIT_QUEUE_HEADER, ELAN_WAIT_QUEUE_HEADER,
...@@ -143,9 +152,12 @@ struct elants_data { ...@@ -143,9 +152,12 @@ struct elants_data {
unsigned int y_res; unsigned int y_res;
unsigned int x_max; unsigned int x_max;
unsigned int y_max; unsigned int y_max;
unsigned int phy_x;
unsigned int phy_y;
struct touchscreen_properties prop; struct touchscreen_properties prop;
enum elants_state state; enum elants_state state;
enum elants_chip_id chip_id;
enum elants_iap_mode iap_mode; enum elants_iap_mode iap_mode;
/* Guards against concurrent access to the device via sysfs */ /* Guards against concurrent access to the device via sysfs */
...@@ -433,7 +445,51 @@ static int elants_i2c_query_bc_version(struct elants_data *ts) ...@@ -433,7 +445,51 @@ static int elants_i2c_query_bc_version(struct elants_data *ts)
return 0; return 0;
} }
static int elants_i2c_query_ts_info(struct elants_data *ts) static int elants_i2c_query_ts_info_ektf(struct elants_data *ts)
{
struct i2c_client *client = ts->client;
int error;
u8 resp[4];
u16 phy_x, phy_y;
const u8 get_xres_cmd[] = {
CMD_HEADER_READ, E_ELAN_INFO_X_RES, 0x00, 0x00
};
const u8 get_yres_cmd[] = {
CMD_HEADER_READ, E_ELAN_INFO_Y_RES, 0x00, 0x00
};
/* Get X/Y size in mm */
error = elants_i2c_execute_command(client, get_xres_cmd,
sizeof(get_xres_cmd),
resp, sizeof(resp), 1,
"get X size");
if (error)
return error;
phy_x = resp[2] | ((resp[3] & 0xF0) << 4);
error = elants_i2c_execute_command(client, get_yres_cmd,
sizeof(get_yres_cmd),
resp, sizeof(resp), 1,
"get Y size");
if (error)
return error;
phy_y = resp[2] | ((resp[3] & 0xF0) << 4);
dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
ts->phy_x = phy_x;
ts->phy_y = phy_y;
/* eKTF doesn't report max size, set it to default values */
ts->x_max = 2240 - 1;
ts->y_max = 1408 - 1;
return 0;
}
static int elants_i2c_query_ts_info_ekth(struct elants_data *ts)
{ {
struct i2c_client *client = ts->client; struct i2c_client *client = ts->client;
int error; int error;
...@@ -508,6 +564,8 @@ static int elants_i2c_query_ts_info(struct elants_data *ts) ...@@ -508,6 +564,8 @@ static int elants_i2c_query_ts_info(struct elants_data *ts)
ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x); ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x);
ts->y_max = ELAN_TS_RESOLUTION(cols, osr); ts->y_max = ELAN_TS_RESOLUTION(cols, osr);
ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y); ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y);
ts->phy_x = phy_x;
ts->phy_y = phy_y;
} }
return 0; return 0;
...@@ -587,8 +645,19 @@ static int elants_i2c_initialize(struct elants_data *ts) ...@@ -587,8 +645,19 @@ static int elants_i2c_initialize(struct elants_data *ts)
error = elants_i2c_query_fw_version(ts); error = elants_i2c_query_fw_version(ts);
if (!error) if (!error)
error = elants_i2c_query_test_version(ts); error = elants_i2c_query_test_version(ts);
switch (ts->chip_id) {
case EKTH3500:
if (!error)
error = elants_i2c_query_ts_info_ekth(ts);
break;
case EKTF3624:
if (!error) if (!error)
error = elants_i2c_query_ts_info(ts); error = elants_i2c_query_ts_info_ektf(ts);
break;
default:
BUG();
}
if (error) if (error)
ts->iap_mode = ELAN_IAP_RECOVERY; ts->iap_mode = ELAN_IAP_RECOVERY;
...@@ -853,7 +922,8 @@ static int elants_i2c_fw_update(struct elants_data *ts) ...@@ -853,7 +922,8 @@ static int elants_i2c_fw_update(struct elants_data *ts)
* Event reporting. * Event reporting.
*/ */
static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf,
size_t packet_size)
{ {
struct input_dev *input = ts->input; struct input_dev *input = ts->input;
unsigned int n_fingers; unsigned int n_fingers;
...@@ -880,8 +950,24 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) ...@@ -880,8 +950,24 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
pos = &buf[FW_POS_XY + i * 3]; pos = &buf[FW_POS_XY + i * 3];
x = (((u16)pos[0] & 0xf0) << 4) | pos[1]; x = (((u16)pos[0] & 0xf0) << 4) | pos[1];
y = (((u16)pos[0] & 0x0f) << 8) | pos[2]; y = (((u16)pos[0] & 0x0f) << 8) | pos[2];
/*
* eKTF3624 may have use "old" touch-report format,
* depending on a device and TS firmware version.
* For example, ASUS Transformer devices use the "old"
* format, while ASUS Nexus 7 uses the "new" formant.
*/
if (packet_size == PACKET_SIZE_OLD &&
ts->chip_id == EKTF3624) {
w = buf[FW_POS_WIDTH + i / 2];
w >>= 4 * (~i & 1);
w |= w << 4;
w |= !w;
p = w;
} else {
p = buf[FW_POS_PRESSURE + i]; p = buf[FW_POS_PRESSURE + i];
w = buf[FW_POS_WIDTH + i]; w = buf[FW_POS_WIDTH + i];
}
dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n", dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n",
i, x, y, p, w); i, x, y, p, w);
...@@ -913,7 +999,8 @@ static u8 elants_i2c_calculate_checksum(u8 *buf) ...@@ -913,7 +999,8 @@ static u8 elants_i2c_calculate_checksum(u8 *buf)
return checksum; return checksum;
} }
static void elants_i2c_event(struct elants_data *ts, u8 *buf) static void elants_i2c_event(struct elants_data *ts, u8 *buf,
size_t packet_size)
{ {
u8 checksum = elants_i2c_calculate_checksum(buf); u8 checksum = elants_i2c_calculate_checksum(buf);
...@@ -927,7 +1014,7 @@ static void elants_i2c_event(struct elants_data *ts, u8 *buf) ...@@ -927,7 +1014,7 @@ static void elants_i2c_event(struct elants_data *ts, u8 *buf)
"%s: unknown packet type: %02x\n", "%s: unknown packet type: %02x\n",
__func__, buf[FW_POS_HEADER]); __func__, buf[FW_POS_HEADER]);
else else
elants_i2c_mt_event(ts, buf); elants_i2c_mt_event(ts, buf, packet_size);
} }
static irqreturn_t elants_i2c_irq(int irq, void *_dev) static irqreturn_t elants_i2c_irq(int irq, void *_dev)
...@@ -970,7 +1057,6 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) ...@@ -970,7 +1057,6 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
switch (ts->buf[FW_HDR_TYPE]) { switch (ts->buf[FW_HDR_TYPE]) {
case CMD_HEADER_HELLO: case CMD_HEADER_HELLO:
case CMD_HEADER_RESP: case CMD_HEADER_RESP:
case CMD_HEADER_REK:
break; break;
case QUEUE_HEADER_WAIT: case QUEUE_HEADER_WAIT:
...@@ -985,9 +1071,24 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) ...@@ -985,9 +1071,24 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
break; break;
case QUEUE_HEADER_SINGLE: case QUEUE_HEADER_SINGLE:
elants_i2c_event(ts, &ts->buf[HEADER_SIZE]); elants_i2c_event(ts, &ts->buf[HEADER_SIZE],
ts->buf[FW_HDR_LENGTH]);
break; break;
case QUEUE_HEADER_NORMAL2: /* CMD_HEADER_REK */
/*
* Depending on firmware version, eKTF3624 touchscreens
* may utilize one of these opcodes for the touch events:
* 0x63 (NORMAL) and 0x66 (NORMAL2). The 0x63 is used by
* older firmware version and differs from 0x66 such that
* touch pressure value needs to be adjusted. The 0x66
* opcode of newer firmware is equal to 0x63 of eKTH3500.
*/
if (ts->chip_id != EKTF3624)
break;
fallthrough;
case QUEUE_HEADER_NORMAL: case QUEUE_HEADER_NORMAL:
report_count = ts->buf[FW_HDR_COUNT]; report_count = ts->buf[FW_HDR_COUNT];
if (report_count == 0 || report_count > 3) { if (report_count == 0 || report_count > 3) {
...@@ -998,7 +1099,12 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) ...@@ -998,7 +1099,12 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
} }
report_len = ts->buf[FW_HDR_LENGTH] / report_count; report_len = ts->buf[FW_HDR_LENGTH] / report_count;
if (report_len != PACKET_SIZE) {
if (report_len == PACKET_SIZE_OLD &&
ts->chip_id == EKTF3624) {
dev_dbg_once(&client->dev,
"using old report format\n");
} else if (report_len != PACKET_SIZE) {
dev_err(&client->dev, dev_err(&client->dev,
"mismatching report length: %*ph\n", "mismatching report length: %*ph\n",
HEADER_SIZE, ts->buf); HEADER_SIZE, ts->buf);
...@@ -1007,8 +1113,8 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev) ...@@ -1007,8 +1113,8 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
for (i = 0; i < report_count; i++) { for (i = 0; i < report_count; i++) {
u8 *buf = ts->buf + HEADER_SIZE + u8 *buf = ts->buf + HEADER_SIZE +
i * PACKET_SIZE; i * report_len;
elants_i2c_event(ts, buf); elants_i2c_event(ts, buf, report_len);
} }
break; break;
...@@ -1250,6 +1356,7 @@ static int elants_i2c_probe(struct i2c_client *client, ...@@ -1250,6 +1356,7 @@ static int elants_i2c_probe(struct i2c_client *client,
init_completion(&ts->cmd_done); init_completion(&ts->cmd_done);
ts->client = client; ts->client = client;
ts->chip_id = (enum elants_chip_id)id->driver_data;
i2c_set_clientdata(client, ts); i2c_set_clientdata(client, ts);
ts->vcc33 = devm_regulator_get(&client->dev, "vcc33"); ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
...@@ -1331,13 +1438,20 @@ static int elants_i2c_probe(struct i2c_client *client, ...@@ -1331,13 +1438,20 @@ static int elants_i2c_probe(struct i2c_client *client,
input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0); input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE, input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE,
0, MT_TOOL_PALM, 0, 0); 0, MT_TOOL_PALM, 0, 0);
touchscreen_parse_properties(ts->input, true, &ts->prop);
if (ts->chip_id == EKTF3624) {
/* calculate resolution from size */
ts->x_res = DIV_ROUND_CLOSEST(ts->prop.max_x, ts->phy_x);
ts->y_res = DIV_ROUND_CLOSEST(ts->prop.max_y, ts->phy_y);
}
input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res); input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
if (ts->major_res > 0) if (ts->major_res > 0)
input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, ts->major_res); input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, ts->major_res);
touchscreen_parse_properties(ts->input, true, &ts->prop);
error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) { if (error) {
...@@ -1466,14 +1580,16 @@ static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops, ...@@ -1466,14 +1580,16 @@ static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
elants_i2c_suspend, elants_i2c_resume); elants_i2c_suspend, elants_i2c_resume);
static const struct i2c_device_id elants_i2c_id[] = { static const struct i2c_device_id elants_i2c_id[] = {
{ DEVICE_NAME, 0 }, { DEVICE_NAME, EKTH3500 },
{ "ekth3500", EKTH3500 },
{ "ektf3624", EKTF3624 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, elants_i2c_id); MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id elants_acpi_id[] = { static const struct acpi_device_id elants_acpi_id[] = {
{ "ELAN0001", 0 }, { "ELAN0001", EKTH3500 },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, elants_acpi_id); MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
...@@ -1482,6 +1598,7 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id); ...@@ -1482,6 +1598,7 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id elants_of_match[] = { static const struct of_device_id elants_of_match[] = {
{ .compatible = "elan,ekth3500" }, { .compatible = "elan,ekth3500" },
{ .compatible = "elan,ektf3624" },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, elants_of_match); MODULE_DEVICE_TABLE(of, elants_of_match);
......
...@@ -341,8 +341,10 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) ...@@ -341,8 +341,10 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
switch (elo->id) { switch (elo->id) {
case 0: /* 10-byte protocol */ case 0: /* 10-byte protocol */
if (elo_setup_10(elo)) if (elo_setup_10(elo)) {
err = -EIO;
goto fail3; goto fail3;
}
break; break;
......
This diff is collapsed.
...@@ -465,13 +465,13 @@ static void mip4_report_keys(struct mip4_ts *ts, u8 *packet) ...@@ -465,13 +465,13 @@ static void mip4_report_keys(struct mip4_ts *ts, u8 *packet)
static void mip4_report_touch(struct mip4_ts *ts, u8 *packet) static void mip4_report_touch(struct mip4_ts *ts, u8 *packet)
{ {
int id; int id;
bool hover; bool __always_unused hover;
bool palm; bool __always_unused palm;
bool state; bool state;
u16 x, y; u16 x, y;
u8 pressure_stage = 0; u8 __always_unused pressure_stage = 0;
u8 pressure; u8 pressure;
u8 size; u8 __always_unused size;
u8 touch_major; u8 touch_major;
u8 touch_minor; u8 touch_minor;
......
...@@ -445,6 +445,7 @@ static int raydium_i2c_write_object(struct i2c_client *client, ...@@ -445,6 +445,7 @@ static int raydium_i2c_write_object(struct i2c_client *client,
enum raydium_bl_ack state) enum raydium_bl_ack state)
{ {
int error; int error;
static const u8 cmd[] = { 0xFF, 0x39 };
error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len); error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len);
if (error) { if (error) {
...@@ -453,7 +454,7 @@ static int raydium_i2c_write_object(struct i2c_client *client, ...@@ -453,7 +454,7 @@ static int raydium_i2c_write_object(struct i2c_client *client,
return error; return error;
} }
error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0); error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, cmd, sizeof(cmd));
if (error) { if (error) {
dev_err(&client->dev, "Ack obj command failed: %d\n", error); dev_err(&client->dev, "Ack obj command failed: %d\n", error);
return error; return error;
......
...@@ -94,8 +94,13 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts) ...@@ -94,8 +94,13 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
for (retries = 10; retries; retries--) { for (retries = 10; retries; retries--) {
error = st1232_ts_read_data(ts, REG_STATUS, 1); error = st1232_ts_read_data(ts, REG_STATUS, 1);
if (!error && ts->read_buf[0] == (STATUS_NORMAL | ERROR_NONE)) if (!error) {
switch (ts->read_buf[0]) {
case STATUS_NORMAL | ERROR_NONE:
case STATUS_IDLE | ERROR_NONE:
return 0; return 0;
}
}
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
* @idev: registered input device * @idev: registered input device
* @work: a work item used to scan the device * @work: a work item used to scan the device
* @dev: a pointer back to the MFD cell struct device* * @dev: a pointer back to the MFD cell struct device*
* @prop: Touchscreen properties
* @ave_ctrl: Sample average control * @ave_ctrl: Sample average control
* (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples) * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
* @touch_det_delay: Touch detect interrupt delay * @touch_det_delay: Touch detect interrupt delay
......
...@@ -787,6 +787,7 @@ static int sur40_probe(struct usb_interface *interface, ...@@ -787,6 +787,7 @@ static int sur40_probe(struct usb_interface *interface,
dev_err(&interface->dev, dev_err(&interface->dev,
"Unable to register video controls."); "Unable to register video controls.");
v4l2_ctrl_handler_free(&sur40->hdl); v4l2_ctrl_handler_free(&sur40->hdl);
error = sur40->hdl.error;
goto err_unreg_v4l2; goto err_unreg_v4l2;
} }
......
...@@ -94,9 +94,7 @@ static void surface3_spi_report_touch(struct surface3_ts_data *ts_data, ...@@ -94,9 +94,7 @@ static void surface3_spi_report_touch(struct surface3_ts_data *ts_data,
static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data) static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data)
{ {
u16 timestamp;
unsigned int i; unsigned int i;
timestamp = get_unaligned_le16(&data[15]);
for (i = 0; i < 13; i++) { for (i = 0; i < 13; i++) {
struct surface3_ts_data_finger *finger; struct surface3_ts_data_finger *finger;
......
...@@ -1044,6 +1044,7 @@ static void nexio_exit(struct usbtouch_usb *usbtouch) ...@@ -1044,6 +1044,7 @@ static void nexio_exit(struct usbtouch_usb *usbtouch)
static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
{ {
struct device *dev = &usbtouch->interface->dev;
struct nexio_touch_packet *packet = (void *) pkt; struct nexio_touch_packet *packet = (void *) pkt;
struct nexio_priv *priv = usbtouch->priv; struct nexio_priv *priv = usbtouch->priv;
unsigned int data_len = be16_to_cpu(packet->data_len); unsigned int data_len = be16_to_cpu(packet->data_len);
...@@ -1062,6 +1063,8 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) ...@@ -1062,6 +1063,8 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
/* send ACK */ /* send ACK */
ret = usb_submit_urb(priv->ack, GFP_ATOMIC); ret = usb_submit_urb(priv->ack, GFP_ATOMIC);
if (ret)
dev_warn(dev, "Failed to submit ACK URB: %d\n", ret);
if (!usbtouch->type->max_xc) { if (!usbtouch->type->max_xc) {
usbtouch->type->max_xc = 2 * x_len; usbtouch->type->max_xc = 2 * x_len;
......
...@@ -161,7 +161,7 @@ static int zinitix_read_data(struct i2c_client *client, ...@@ -161,7 +161,7 @@ static int zinitix_read_data(struct i2c_client *client,
ret = i2c_master_recv(client, (u8 *)values, length); ret = i2c_master_recv(client, (u8 *)values, length);
if (ret != length) if (ret != length)
return ret < 0 ? ret : -EIO; ; return ret < 0 ? ret : -EIO;
return 0; return 0;
} }
...@@ -190,7 +190,7 @@ static int zinitix_write_cmd(struct i2c_client *client, u16 reg) ...@@ -190,7 +190,7 @@ static int zinitix_write_cmd(struct i2c_client *client, u16 reg)
return 0; return 0;
} }
static bool zinitix_init_touch(struct bt541_ts_data *bt541) static int zinitix_init_touch(struct bt541_ts_data *bt541)
{ {
struct i2c_client *client = bt541->client; struct i2c_client *client = bt541->client;
int i; int i;
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This header provides the constants of the standard Chrome OS key matrix
* for cros-ec keyboard-controller bindings.
*
* Copyright (c) 2021 Google, Inc
*/
#ifndef _CROS_EC_KEYBOARD_H
#define _CROS_EC_KEYBOARD_H
#define CROS_STD_TOP_ROW_KEYMAP \
MATRIX_KEY(0x00, 0x02, KEY_F1) \
MATRIX_KEY(0x03, 0x02, KEY_F2) \
MATRIX_KEY(0x02, 0x02, KEY_F3) \
MATRIX_KEY(0x01, 0x02, KEY_F4) \
MATRIX_KEY(0x03, 0x04, KEY_F5) \
MATRIX_KEY(0x02, 0x04, KEY_F6) \
MATRIX_KEY(0x01, 0x04, KEY_F7) \
MATRIX_KEY(0x02, 0x09, KEY_F8) \
MATRIX_KEY(0x01, 0x09, KEY_F9) \
MATRIX_KEY(0x00, 0x04, KEY_F10)
#define CROS_STD_MAIN_KEYMAP \
MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA) \
MATRIX_KEY(0x00, 0x03, KEY_B) \
MATRIX_KEY(0x00, 0x05, KEY_RO) \
MATRIX_KEY(0x00, 0x06, KEY_N) \
MATRIX_KEY(0x00, 0x08, KEY_EQUAL) \
MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT) \
MATRIX_KEY(0x01, 0x01, KEY_ESC) \
MATRIX_KEY(0x01, 0x03, KEY_G) \
MATRIX_KEY(0x01, 0x06, KEY_H) \
MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE) \
MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE) \
MATRIX_KEY(0x01, 0x0c, KEY_HENKAN) \
\
MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL) \
MATRIX_KEY(0x02, 0x01, KEY_TAB) \
MATRIX_KEY(0x02, 0x03, KEY_T) \
MATRIX_KEY(0x02, 0x05, KEY_RIGHTBRACE) \
MATRIX_KEY(0x02, 0x06, KEY_Y) \
MATRIX_KEY(0x02, 0x07, KEY_102ND) \
MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE) \
MATRIX_KEY(0x02, 0x0a, KEY_YEN) \
\
MATRIX_KEY(0x03, 0x00, KEY_LEFTMETA) \
MATRIX_KEY(0x03, 0x01, KEY_GRAVE) \
MATRIX_KEY(0x03, 0x03, KEY_5) \
MATRIX_KEY(0x03, 0x06, KEY_6) \
MATRIX_KEY(0x03, 0x08, KEY_MINUS) \
MATRIX_KEY(0x03, 0x09, KEY_SLEEP) \
MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH) \
MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN) \
\
MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL) \
MATRIX_KEY(0x04, 0x01, KEY_A) \
MATRIX_KEY(0x04, 0x02, KEY_D) \
MATRIX_KEY(0x04, 0x03, KEY_F) \
MATRIX_KEY(0x04, 0x04, KEY_S) \
MATRIX_KEY(0x04, 0x05, KEY_K) \
MATRIX_KEY(0x04, 0x06, KEY_J) \
MATRIX_KEY(0x04, 0x08, KEY_SEMICOLON) \
MATRIX_KEY(0x04, 0x09, KEY_L) \
MATRIX_KEY(0x04, 0x0a, KEY_BACKSLASH) \
MATRIX_KEY(0x04, 0x0b, KEY_ENTER) \
\
MATRIX_KEY(0x05, 0x01, KEY_Z) \
MATRIX_KEY(0x05, 0x02, KEY_C) \
MATRIX_KEY(0x05, 0x03, KEY_V) \
MATRIX_KEY(0x05, 0x04, KEY_X) \
MATRIX_KEY(0x05, 0x05, KEY_COMMA) \
MATRIX_KEY(0x05, 0x06, KEY_M) \
MATRIX_KEY(0x05, 0x07, KEY_LEFTSHIFT) \
MATRIX_KEY(0x05, 0x08, KEY_SLASH) \
MATRIX_KEY(0x05, 0x09, KEY_DOT) \
MATRIX_KEY(0x05, 0x0b, KEY_SPACE) \
\
MATRIX_KEY(0x06, 0x01, KEY_1) \
MATRIX_KEY(0x06, 0x02, KEY_3) \
MATRIX_KEY(0x06, 0x03, KEY_4) \
MATRIX_KEY(0x06, 0x04, KEY_2) \
MATRIX_KEY(0x06, 0x05, KEY_8) \
MATRIX_KEY(0x06, 0x06, KEY_7) \
MATRIX_KEY(0x06, 0x08, KEY_0) \
MATRIX_KEY(0x06, 0x09, KEY_9) \
MATRIX_KEY(0x06, 0x0a, KEY_LEFTALT) \
MATRIX_KEY(0x06, 0x0b, KEY_DOWN) \
MATRIX_KEY(0x06, 0x0c, KEY_RIGHT) \
\
MATRIX_KEY(0x07, 0x01, KEY_Q) \
MATRIX_KEY(0x07, 0x02, KEY_E) \
MATRIX_KEY(0x07, 0x03, KEY_R) \
MATRIX_KEY(0x07, 0x04, KEY_W) \
MATRIX_KEY(0x07, 0x05, KEY_I) \
MATRIX_KEY(0x07, 0x06, KEY_U) \
MATRIX_KEY(0x07, 0x07, KEY_RIGHTSHIFT) \
MATRIX_KEY(0x07, 0x08, KEY_P) \
MATRIX_KEY(0x07, 0x09, KEY_O) \
MATRIX_KEY(0x07, 0x0b, KEY_UP) \
MATRIX_KEY(0x07, 0x0c, KEY_LEFT)
#endif /* _CROS_EC_KEYBOARD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment