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:
if the EC does not have its own logic or hardware for this.
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:
- compatible
......@@ -38,11 +49,24 @@ unevaluatedProperties: false
examples:
- |
#include <dt-bindings/input/input.h>
cros-ec-keyb {
compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>;
keypad,num-columns = <13>;
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
* RR=Row CC=Column KKKK=Key Code
......
......@@ -6,103 +6,18 @@
*/
#include <dt-bindings/input/input.h>
#include <dt-bindings/input/cros-ec-keyboard.h>
&cros_ec {
keyboard-controller {
keyboard_controller: keyboard-controller {
compatible = "google,cros-ec-keyb";
keypad,num-rows = <8>;
keypad,num-columns = <13>;
google,needs-ghost-filter;
linux,keymap = <
MATRIX_KEY(0x00, 0x01, KEY_LEFTMETA)
MATRIX_KEY(0x00, 0x02, KEY_F1)
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)
CROS_STD_TOP_ROW_KEYMAP
CROS_STD_MAIN_KEYMAP
>;
};
};
......@@ -456,7 +456,7 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
if (IS_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) {
retval = -EINVAL;
goto out;
......@@ -480,6 +480,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
int i;
int retval = 0;
if (len % sizeof(*keypam))
return -EINVAL;
len = min(len, sizeof(joydev->keypam));
/* Validate the map. */
......@@ -487,7 +490,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
if (IS_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) {
retval = -EINVAL;
goto out;
......
......@@ -382,4 +382,11 @@ config JOYSTICK_FSIA6B
To compile this driver as a module, choose M here: the
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
......@@ -24,6 +24,7 @@ obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_N64) += n64joy.o
obj-$(CONFIG_JOYSTICK_PSXPAD_SPI) += psxpad-spi.o
obj-$(CONFIG_JOYSTICK_PXRC) += pxrc.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
......@@ -37,4 +38,3 @@ obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.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 {
{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
......
......@@ -446,7 +446,7 @@ config KEYBOARD_MPR121
config KEYBOARD_SNVS_PWRKEY
tristate "IMX SNVS Power Key Driver"
depends on ARCH_MXC || COMPILE_TEST
depends on ARCH_MXC || (COMPILE_TEST && HAS_IOMEM)
depends on OF
help
This is the snvs powerkey driver for the Freescale i.MX application
......@@ -685,7 +685,7 @@ config KEYBOARD_OMAP
config KEYBOARD_OMAP4
tristate "TI OMAP4+ keypad support"
depends on OF || ARCH_OMAP2PLUS
depends on (OF && HAS_IOMEM) || ARCH_OMAP2PLUS
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the OMAP4+ keypad.
......@@ -773,7 +773,7 @@ config KEYBOARD_CAP11XX
config KEYBOARD_BCM
tristate "Broadcom keypad driver"
depends on OF && HAVE_CLK
depends on OF && HAVE_CLK && HAS_IOMEM
select INPUT_MATRIXKMAP
default ARCH_BCM_CYGNUS
help
......
......@@ -48,6 +48,7 @@
#include <linux/efi.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/ktime.h>
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/spinlock.h>
......@@ -409,7 +410,7 @@ struct applespi_data {
unsigned int cmd_msg_cntr;
/* lock to protect the above parameters and flags below */
spinlock_t cmd_msg_lock;
bool cmd_msg_queued;
ktime_t cmd_msg_queued;
enum applespi_evt_type cmd_evt_type;
struct led_classdev backlight_info;
......@@ -729,7 +730,7 @@ static void applespi_msg_complete(struct applespi_data *applespi,
wake_up_all(&applespi->drain_complete);
if (is_write_msg) {
applespi->cmd_msg_queued = false;
applespi->cmd_msg_queued = 0;
applespi_send_cmd_msg(applespi);
}
......@@ -748,6 +749,8 @@ static void applespi_async_write_complete(void *context)
applespi->tx_status,
APPLESPI_STATUS_SIZE);
udelay(SPI_RW_CHG_DELAY_US);
if (!applespi_check_write_status(applespi, applespi->wr_m.status)) {
/*
* If we got an error, we presumably won't get the expected
......@@ -771,8 +774,16 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)
return 0;
/* check whether send is in progress */
if (applespi->cmd_msg_queued)
return 0;
if (applespi->cmd_msg_queued) {
if (ktime_ms_delta(ktime_get(), applespi->cmd_msg_queued) < 1000)
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 */
memset(packet, 0, APPLESPI_PACKET_SIZE);
......@@ -869,7 +880,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi)
return sts;
}
applespi->cmd_msg_queued = true;
applespi->cmd_msg_queued = ktime_get_coarse();
applespi->write_active = true;
return 0;
......@@ -1921,7 +1932,7 @@ static int __maybe_unused applespi_resume(struct device *dev)
applespi->drain = false;
applespi->have_cl_led_on = false;
applespi->have_bl_level = 0;
applespi->cmd_msg_queued = false;
applespi->cmd_msg_queued = 0;
applespi->read_active = false;
applespi->write_active = false;
......
......@@ -27,6 +27,8 @@
#include <asm/unaligned.h>
#define MAX_NUM_TOP_ROW_KEYS 15
/**
* struct cros_ec_keyb - Structure representing EC keyboard device
*
......@@ -42,6 +44,9 @@
* @idev: The input device for the matrix keys.
* @bs_idev: The input device for non-matrix buttons and switches (or NULL).
* @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 {
unsigned int rows;
......@@ -58,6 +63,9 @@ struct cros_ec_keyb {
struct input_dev *idev;
struct input_dev *bs_idev;
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)
struct input_dev *idev;
const char *phys;
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);
if (err)
......@@ -578,6 +591,21 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
ckdev->idev = idev;
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);
if (err) {
dev_err(dev, "cannot register input device\n");
......@@ -587,6 +615,51 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
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)
{
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)
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;
err = blocking_notifier_chain_register(&ckdev->ec->event_notifier,
&ckdev->notifier);
......
This diff is collapsed.
......@@ -863,6 +863,7 @@ static void da7280_parse_properties(struct device *dev,
gpi_str3[7] = '0' + i;
haptics->gpi_ctl[i].polarity = 0;
error = device_property_read_string(dev, gpi_str3, &str);
if (!error)
haptics->gpi_ctl[i].polarity =
da7280_haptic_of_gpi_pol_str(dev, str);
}
......@@ -1299,11 +1300,13 @@ static int __maybe_unused da7280_resume(struct device *dev)
return retval;
}
#ifdef CONFIG_OF
static const struct of_device_id da7280_of_match[] = {
{ .compatible = "dlg,da7280", },
{ }
};
MODULE_DEVICE_TABLE(of, da7280_of_match);
#endif
static const struct i2c_device_id da7280_i2c_id[] = {
{ "da7280", },
......
......@@ -986,7 +986,7 @@ static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
case V7_PACKET_ID_TWO:
mt[1].x &= ~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) {
mt[1].x = 0;
/* y gets set to 0 at the end of this function */
......
......@@ -1106,8 +1106,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
num_fingers = hw.w + 2;
break;
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;
case 4 ... 15:
if (SYN_CAP_PALMDETECT(info->capabilities))
......
......@@ -255,7 +255,7 @@ config SERIO_ARC_PS2
config SERIO_APBPS2
tristate "GRLIB APBPS2 PS/2 keyboard/mouse controller"
depends on OF
depends on OF && HAS_IOMEM
help
Say Y here if you want support for GRLIB APBPS2 peripherals used
to connect to PS/2 keyboard and/or mouse.
......
......@@ -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_CHASSIS_TYPE, "10"), /* Notebook */
},
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
},
},
{ }
};
......
......@@ -1036,9 +1036,9 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
input_abs_get_max(aiptek->inputdev, ABS_X) + 1,
input_abs_get_max(aiptek->inputdev, ABS_Y) + 1);
return sysfs_emit(buf, "%dx%d\n",
input_abs_get_max(aiptek->inputdev, ABS_X) + 1,
input_abs_get_max(aiptek->inputdev, ABS_Y) + 1);
}
/* These structs define the sysfs files, param #1 is the name of the
......@@ -1064,9 +1064,8 @@ static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(pointer_mode_map,
aiptek->curSetting.pointerMode));
return sysfs_emit(buf, "%s\n", map_val_to_str(pointer_mode_map,
aiptek->curSetting.pointerMode));
}
static ssize_t
......@@ -1101,9 +1100,8 @@ static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attri
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(coordinate_mode_map,
aiptek->curSetting.coordinateMode));
return sysfs_emit(buf, "%s\n", map_val_to_str(coordinate_mode_map,
aiptek->curSetting.coordinateMode));
}
static ssize_t
......@@ -1143,9 +1141,8 @@ static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(tool_mode_map,
aiptek->curSetting.toolMode));
return sysfs_emit(buf, "%s\n", map_val_to_str(tool_mode_map,
aiptek->curSetting.toolMode));
}
static ssize_t
......@@ -1174,10 +1171,9 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
return sysfs_emit(buf, "disable\n");
} else {
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.xTilt);
return sysfs_emit(buf, "%d\n", aiptek->curSetting.xTilt);
}
}
......@@ -1216,10 +1212,9 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
return sysfs_emit(buf, "disable\n");
} else {
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.yTilt);
return sysfs_emit(buf, "%d\n", aiptek->curSetting.yTilt);
}
}
......@@ -1257,7 +1252,7 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut
{
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
......@@ -1286,8 +1281,7 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.programmableDelay);
return sysfs_emit(buf, "%d\n", aiptek->curSetting.programmableDelay);
}
static ssize_t
......@@ -1316,7 +1310,7 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri
{
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);
......@@ -1355,7 +1349,7 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at
default:
return 0;
}
return snprintf(buf, PAGE_SIZE, retMsg);
return sysfs_emit(buf, retMsg);
}
static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
......@@ -1375,9 +1369,8 @@ static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonUpper));
return sysfs_emit(buf, "%s\n", map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonUpper));
}
static ssize_t
......@@ -1406,9 +1399,8 @@ static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonLower));
return sysfs_emit(buf, "%s\n", map_val_to_str(stylus_button_map,
aiptek->curSetting.stylusButtonLower));
}
static ssize_t
......@@ -1444,9 +1436,8 @@ static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonLeft));
return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonLeft));
}
static ssize_t
......@@ -1474,9 +1465,8 @@ static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonMiddle));
return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonMiddle));
}
static ssize_t
......@@ -1504,9 +1494,8 @@ static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s\n",
map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonRight));
return sysfs_emit(buf, "%s\n", map_val_to_str(mouse_button_map,
aiptek->curSetting.mouseButtonRight));
}
static ssize_t
......@@ -1535,10 +1524,9 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
return sysfs_emit(buf, "disable\n");
} else {
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.wheel);
return sysfs_emit(buf, "%d\n", aiptek->curSetting.wheel);
}
}
......@@ -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
* is in order...
*/
return snprintf(buf, PAGE_SIZE,
"Write anything to this file to program your tablet.\n");
return sysfs_emit(buf, "Write anything to this file to program your tablet.\n");
}
static ssize_t
......@@ -1600,7 +1587,7 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a
{
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);
......@@ -1613,7 +1600,7 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute
{
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);
......@@ -1626,8 +1613,7 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%04x\n",
aiptek->features.firmwareCode);
return sysfs_emit(buf, "%04x\n", aiptek->features.firmwareCode);
}
static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
......
......@@ -608,7 +608,7 @@ config TOUCHSCREEN_MTOUCH
config TOUCHSCREEN_IMX6UL_TSC
tristate "Freescale i.MX6UL touchscreen controller"
depends on (OF && GPIOLIB) || COMPILE_TEST
depends on ((OF && GPIOLIB) || COMPILE_TEST) && HAS_IOMEM
help
Say Y here if you have a Freescale i.MX6UL, and want to
use the internal touchscreen controller.
......
This diff is collapsed.
......@@ -56,6 +56,7 @@
#define QUEUE_HEADER_SINGLE 0x62
#define QUEUE_HEADER_NORMAL 0X63
#define QUEUE_HEADER_WAIT 0x64
#define QUEUE_HEADER_NORMAL2 0x66
/* Command header definition */
#define CMD_HEADER_WRITE 0x54
......@@ -69,6 +70,7 @@
#define CMD_HEADER_REK 0x66
/* FW position data */
#define PACKET_SIZE_OLD 40
#define PACKET_SIZE 55
#define MAX_CONTACT_NUM 10
#define FW_POS_HEADER 0
......@@ -90,6 +92,8 @@
/* FW read command, 0x53 0x?? 0x0, 0x01 */
#define E_ELAN_INFO_FW_VER 0x00
#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_TEST_VER 0xE0
#define E_ELAN_INFO_FW_ID 0xF0
......@@ -112,6 +116,11 @@
#define ELAN_POWERON_DELAY_USEC 500
#define ELAN_RESET_DELAY_MSEC 20
enum elants_chip_id {
EKTH3500,
EKTF3624,
};
enum elants_state {
ELAN_STATE_NORMAL,
ELAN_WAIT_QUEUE_HEADER,
......@@ -143,9 +152,12 @@ struct elants_data {
unsigned int y_res;
unsigned int x_max;
unsigned int y_max;
unsigned int phy_x;
unsigned int phy_y;
struct touchscreen_properties prop;
enum elants_state state;
enum elants_chip_id chip_id;
enum elants_iap_mode iap_mode;
/* Guards against concurrent access to the device via sysfs */
......@@ -433,7 +445,51 @@ static int elants_i2c_query_bc_version(struct elants_data *ts)
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;
int error;
......@@ -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->y_max = ELAN_TS_RESOLUTION(cols, osr);
ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y);
ts->phy_x = phy_x;
ts->phy_y = phy_y;
}
return 0;
......@@ -587,8 +645,19 @@ static int elants_i2c_initialize(struct elants_data *ts)
error = elants_i2c_query_fw_version(ts);
if (!error)
error = elants_i2c_query_test_version(ts);
if (!error)
error = elants_i2c_query_ts_info(ts);
switch (ts->chip_id) {
case EKTH3500:
if (!error)
error = elants_i2c_query_ts_info_ekth(ts);
break;
case EKTF3624:
if (!error)
error = elants_i2c_query_ts_info_ektf(ts);
break;
default:
BUG();
}
if (error)
ts->iap_mode = ELAN_IAP_RECOVERY;
......@@ -853,7 +922,8 @@ static int elants_i2c_fw_update(struct elants_data *ts)
* 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;
unsigned int n_fingers;
......@@ -880,8 +950,24 @@ static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
pos = &buf[FW_POS_XY + i * 3];
x = (((u16)pos[0] & 0xf0) << 4) | pos[1];
y = (((u16)pos[0] & 0x0f) << 8) | pos[2];
p = buf[FW_POS_PRESSURE + i];
w = buf[FW_POS_WIDTH + i];
/*
* 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];
w = buf[FW_POS_WIDTH + i];
}
dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n",
i, x, y, p, w);
......@@ -913,7 +999,8 @@ static u8 elants_i2c_calculate_checksum(u8 *buf)
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);
......@@ -927,7 +1014,7 @@ static void elants_i2c_event(struct elants_data *ts, u8 *buf)
"%s: unknown packet type: %02x\n",
__func__, buf[FW_POS_HEADER]);
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)
......@@ -970,7 +1057,6 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
switch (ts->buf[FW_HDR_TYPE]) {
case CMD_HEADER_HELLO:
case CMD_HEADER_RESP:
case CMD_HEADER_REK:
break;
case QUEUE_HEADER_WAIT:
......@@ -985,9 +1071,24 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
break;
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;
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:
report_count = ts->buf[FW_HDR_COUNT];
if (report_count == 0 || report_count > 3) {
......@@ -998,7 +1099,12 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
}
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,
"mismatching report length: %*ph\n",
HEADER_SIZE, ts->buf);
......@@ -1007,8 +1113,8 @@ static irqreturn_t elants_i2c_irq(int irq, void *_dev)
for (i = 0; i < report_count; i++) {
u8 *buf = ts->buf + HEADER_SIZE +
i * PACKET_SIZE;
elants_i2c_event(ts, buf);
i * report_len;
elants_i2c_event(ts, buf, report_len);
}
break;
......@@ -1250,6 +1356,7 @@ static int elants_i2c_probe(struct i2c_client *client,
init_completion(&ts->cmd_done);
ts->client = client;
ts->chip_id = (enum elants_chip_id)id->driver_data;
i2c_set_clientdata(client, ts);
ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
......@@ -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_TOOL_TYPE,
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_Y, ts->y_res);
if (ts->major_res > 0)
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,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) {
......@@ -1466,14 +1580,16 @@ static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
elants_i2c_suspend, elants_i2c_resume);
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);
#ifdef CONFIG_ACPI
static const struct acpi_device_id elants_acpi_id[] = {
{ "ELAN0001", 0 },
{ "ELAN0001", EKTH3500 },
{ }
};
MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
......@@ -1482,6 +1598,7 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
#ifdef CONFIG_OF
static const struct of_device_id elants_of_match[] = {
{ .compatible = "elan,ekth3500" },
{ .compatible = "elan,ektf3624" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, elants_of_match);
......
......@@ -341,8 +341,10 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
switch (elo->id) {
case 0: /* 10-byte protocol */
if (elo_setup_10(elo))
if (elo_setup_10(elo)) {
err = -EIO;
goto fail3;
}
break;
......
This diff is collapsed.
......@@ -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)
{
int id;
bool hover;
bool palm;
bool __always_unused hover;
bool __always_unused palm;
bool state;
u16 x, y;
u8 pressure_stage = 0;
u8 __always_unused pressure_stage = 0;
u8 pressure;
u8 size;
u8 __always_unused size;
u8 touch_major;
u8 touch_minor;
......
......@@ -445,6 +445,7 @@ static int raydium_i2c_write_object(struct i2c_client *client,
enum raydium_bl_ack state)
{
int error;
static const u8 cmd[] = { 0xFF, 0x39 };
error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len);
if (error) {
......@@ -453,7 +454,7 @@ static int raydium_i2c_write_object(struct i2c_client *client,
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) {
dev_err(&client->dev, "Ack obj command failed: %d\n", error);
return error;
......
......@@ -94,8 +94,13 @@ static int st1232_ts_wait_ready(struct st1232_ts_data *ts)
for (retries = 10; retries; retries--) {
error = st1232_ts_read_data(ts, REG_STATUS, 1);
if (!error && ts->read_buf[0] == (STATUS_NORMAL | ERROR_NONE))
return 0;
if (!error) {
switch (ts->read_buf[0]) {
case STATUS_NORMAL | ERROR_NONE:
case STATUS_IDLE | ERROR_NONE:
return 0;
}
}
usleep_range(1000, 2000);
}
......
......@@ -52,6 +52,7 @@
* @idev: registered input device
* @work: a work item used to scan the device
* @dev: a pointer back to the MFD cell struct device*
* @prop: Touchscreen properties
* @ave_ctrl: Sample average control
* (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
* @touch_det_delay: Touch detect interrupt delay
......
......@@ -787,6 +787,7 @@ static int sur40_probe(struct usb_interface *interface,
dev_err(&interface->dev,
"Unable to register video controls.");
v4l2_ctrl_handler_free(&sur40->hdl);
error = sur40->hdl.error;
goto err_unreg_v4l2;
}
......
......@@ -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)
{
u16 timestamp;
unsigned int i;
timestamp = get_unaligned_le16(&data[15]);
for (i = 0; i < 13; i++) {
struct surface3_ts_data_finger *finger;
......
......@@ -1044,6 +1044,7 @@ static void nexio_exit(struct usbtouch_usb *usbtouch)
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_priv *priv = usbtouch->priv;
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)
/* send ACK */
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) {
usbtouch->type->max_xc = 2 * x_len;
......
......@@ -161,7 +161,7 @@ static int zinitix_read_data(struct i2c_client *client,
ret = i2c_master_recv(client, (u8 *)values, length);
if (ret != length)
return ret < 0 ? ret : -EIO; ;
return ret < 0 ? ret : -EIO;
return 0;
}
......@@ -190,7 +190,7 @@ static int zinitix_write_cmd(struct i2c_client *client, u16 reg)
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;
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