Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input subsystem updates from Dmitry Torokhov: "A fix for MT breakage, enhancement to Elantech PS/2 driver and a couple of assorted fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: elantech - add support for trackpoint found on some v3 models Input: elantech - reset the device when elantech probe fails Input: ALPS - suppress message about 'Unknown touchpad' Input: fix used slots detection breakage Input: sparc - i8042-sparcio.h: fix unused kbd_res warning Input: atmel_mxt_ts - improve description of gpio-keymap property
This commit is contained in:
commit
44bf091f50
|
@ -15,6 +15,17 @@ Optional properties for main touchpad device:
|
|||
keycode generated by each GPIO. Linux keycodes are defined in
|
||||
<dt-bindings/input/input.h>.
|
||||
|
||||
- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages
|
||||
on GPIO bit changes. An array of up to 8 entries can be provided
|
||||
indicating the Linux keycode mapped to each bit of the status byte,
|
||||
starting at the LSB. Linux keycodes are defined in
|
||||
<dt-bindings/input/input.h>.
|
||||
|
||||
Note: the numbering of the GPIOs and the bit they start at varies between
|
||||
maXTouch devices. You must either refer to the documentation, or
|
||||
experiment to determine which bit corresponds to which input. Use
|
||||
KEY_RESERVED for unused padding values.
|
||||
|
||||
Example:
|
||||
|
||||
touch@4b {
|
||||
|
|
|
@ -236,6 +236,18 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
|
|||
}
|
||||
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
|
||||
|
||||
static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mt->num_slots; i++) {
|
||||
if (!input_mt_is_used(mt, &mt->slots[i])) {
|
||||
input_mt_slot(dev, i);
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* input_mt_drop_unused() - Inactivate slots not seen in this frame
|
||||
* @dev: input device with allocated MT slots
|
||||
|
@ -245,19 +257,11 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation);
|
|||
void input_mt_drop_unused(struct input_dev *dev)
|
||||
{
|
||||
struct input_mt *mt = dev->mt;
|
||||
int i;
|
||||
|
||||
if (!mt)
|
||||
return;
|
||||
|
||||
for (i = 0; i < mt->num_slots; i++) {
|
||||
if (!input_mt_is_used(mt, &mt->slots[i])) {
|
||||
input_mt_slot(dev, i);
|
||||
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
}
|
||||
if (mt) {
|
||||
__input_mt_drop_unused(dev, mt);
|
||||
mt->frame++;
|
||||
}
|
||||
|
||||
mt->frame++;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_drop_unused);
|
||||
|
||||
|
@ -278,12 +282,14 @@ void input_mt_sync_frame(struct input_dev *dev)
|
|||
return;
|
||||
|
||||
if (mt->flags & INPUT_MT_DROP_UNUSED)
|
||||
input_mt_drop_unused(dev);
|
||||
__input_mt_drop_unused(dev, mt);
|
||||
|
||||
if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
|
||||
use_count = true;
|
||||
|
||||
input_mt_report_pointer_emulation(dev, use_count);
|
||||
|
||||
mt->frame++;
|
||||
}
|
||||
EXPORT_SYMBOL(input_mt_sync_frame);
|
||||
|
||||
|
|
|
@ -2234,8 +2234,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
psmouse_info(psmouse,
|
||||
"Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
|
||||
psmouse_dbg(psmouse,
|
||||
"Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/input/mt.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/libps2.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "psmouse.h"
|
||||
#include "elantech.h"
|
||||
|
||||
|
@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
|
|||
input_sync(dev);
|
||||
}
|
||||
|
||||
static void elantech_report_trackpoint(struct psmouse *psmouse,
|
||||
int packet_type)
|
||||
{
|
||||
/*
|
||||
* byte 0: 0 0 sx sy 0 M R L
|
||||
* byte 1:~sx 0 0 0 0 0 0 0
|
||||
* byte 2:~sy 0 0 0 0 0 0 0
|
||||
* byte 3: 0 0 ~sy ~sx 0 1 1 0
|
||||
* byte 4: x7 x6 x5 x4 x3 x2 x1 x0
|
||||
* byte 5: y7 y6 y5 y4 y3 y2 y1 y0
|
||||
*
|
||||
* x and y are written in two's complement spread
|
||||
* over 9 bits with sx/sy the relative top bit and
|
||||
* x7..x0 and y7..y0 the lower bits.
|
||||
* The sign of y is opposite to what the input driver
|
||||
* expects for a relative movement
|
||||
*/
|
||||
|
||||
struct elantech_data *etd = psmouse->private;
|
||||
struct input_dev *tp_dev = etd->tp_dev;
|
||||
unsigned char *packet = psmouse->packet;
|
||||
int x, y;
|
||||
u32 t;
|
||||
|
||||
if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
|
||||
!tp_dev,
|
||||
psmouse_fmt("Unexpected trackpoint message\n"))) {
|
||||
if (etd->debug == 1)
|
||||
elantech_packet_dump(psmouse);
|
||||
return;
|
||||
}
|
||||
|
||||
t = get_unaligned_le32(&packet[0]);
|
||||
|
||||
switch (t & ~7U) {
|
||||
case 0x06000030U:
|
||||
case 0x16008020U:
|
||||
case 0x26800010U:
|
||||
case 0x36808000U:
|
||||
x = packet[4] - (int)((packet[1]^0x80) << 1);
|
||||
y = (int)((packet[2]^0x80) << 1) - packet[5];
|
||||
|
||||
input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
|
||||
input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
|
||||
input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
|
||||
|
||||
input_report_rel(tp_dev, REL_X, x);
|
||||
input_report_rel(tp_dev, REL_Y, y);
|
||||
|
||||
input_sync(tp_dev);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Dump unexpected packet sequences if debug=1 (default) */
|
||||
if (etd->debug == 1)
|
||||
elantech_packet_dump(psmouse);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret complete data packets and report absolute mode input events for
|
||||
* hardware version 3. (12 byte packets for two fingers)
|
||||
|
@ -715,6 +778,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
|
|||
|
||||
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
|
||||
return PACKET_V3_TAIL;
|
||||
if ((packet[3] & 0x0f) == 0x06)
|
||||
return PACKET_TRACKPOINT;
|
||||
}
|
||||
|
||||
return PACKET_UNKNOWN;
|
||||
|
@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
|
|||
|
||||
case 3:
|
||||
packet_type = elantech_packet_check_v3(psmouse);
|
||||
/* ignore debounce */
|
||||
if (packet_type == PACKET_DEBOUNCE)
|
||||
return PSMOUSE_FULL_PACKET;
|
||||
|
||||
if (packet_type == PACKET_UNKNOWN)
|
||||
switch (packet_type) {
|
||||
case PACKET_UNKNOWN:
|
||||
return PSMOUSE_BAD_DATA;
|
||||
|
||||
elantech_report_absolute_v3(psmouse, packet_type);
|
||||
case PACKET_DEBOUNCE:
|
||||
/* ignore debounce */
|
||||
break;
|
||||
|
||||
case PACKET_TRACKPOINT:
|
||||
elantech_report_trackpoint(psmouse, packet_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
elantech_report_absolute_v3(psmouse, packet_type);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
|
|||
* Asus UX31 0x361f00 20, 15, 0e clickpad
|
||||
* Asus UX32VD 0x361f02 00, 15, 0e clickpad
|
||||
* Avatar AVIU-145A2 0x361f00 ? clickpad
|
||||
* Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
|
||||
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
|
||||
* Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
|
||||
* Lenovo L530 0x350f02 b9, 15, 0c 2 hw buttons (*)
|
||||
* Samsung NF210 0x150b00 78, 14, 0a 2 hw buttons
|
||||
* Samsung NP770Z5E 0x575f01 10, 15, 0f clickpad
|
||||
* Samsung NP700Z5B 0x361f06 21, 15, 0f clickpad
|
||||
|
@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
|
|||
* Samsung RF710 0x450f00 ? 2 hw buttons
|
||||
* System76 Pangolin 0x250f01 ? 2 hw buttons
|
||||
* (*) + 3 trackpoint buttons
|
||||
* (**) + 0 trackpoint buttons
|
||||
* Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
|
||||
*/
|
||||
static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
|
||||
{
|
||||
|
@ -1324,6 +1402,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
|
|||
*/
|
||||
static void elantech_disconnect(struct psmouse *psmouse)
|
||||
{
|
||||
struct elantech_data *etd = psmouse->private;
|
||||
|
||||
if (etd->tp_dev)
|
||||
input_unregister_device(etd->tp_dev);
|
||||
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
|
||||
&elantech_attr_group);
|
||||
kfree(psmouse->private);
|
||||
|
@ -1438,8 +1520,10 @@ static int elantech_set_properties(struct elantech_data *etd)
|
|||
int elantech_init(struct psmouse *psmouse)
|
||||
{
|
||||
struct elantech_data *etd;
|
||||
int i, error;
|
||||
int i;
|
||||
int error = -EINVAL;
|
||||
unsigned char param[3];
|
||||
struct input_dev *tp_dev;
|
||||
|
||||
psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
|
||||
if (!etd)
|
||||
|
@ -1498,14 +1582,49 @@ int elantech_init(struct psmouse *psmouse)
|
|||
goto init_fail;
|
||||
}
|
||||
|
||||
/* The MSB indicates the presence of the trackpoint */
|
||||
if ((etd->capabilities[0] & 0x80) == 0x80) {
|
||||
tp_dev = input_allocate_device();
|
||||
|
||||
if (!tp_dev) {
|
||||
error = -ENOMEM;
|
||||
goto init_fail_tp_alloc;
|
||||
}
|
||||
|
||||
etd->tp_dev = tp_dev;
|
||||
snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
|
||||
psmouse->ps2dev.serio->phys);
|
||||
tp_dev->phys = etd->tp_phys;
|
||||
tp_dev->name = "Elantech PS/2 TrackPoint";
|
||||
tp_dev->id.bustype = BUS_I8042;
|
||||
tp_dev->id.vendor = 0x0002;
|
||||
tp_dev->id.product = PSMOUSE_ELANTECH;
|
||||
tp_dev->id.version = 0x0000;
|
||||
tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
|
||||
tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
|
||||
tp_dev->relbit[BIT_WORD(REL_X)] =
|
||||
BIT_MASK(REL_X) | BIT_MASK(REL_Y);
|
||||
tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
|
||||
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
|
||||
BIT_MASK(BTN_RIGHT);
|
||||
error = input_register_device(etd->tp_dev);
|
||||
if (error < 0)
|
||||
goto init_fail_tp_reg;
|
||||
}
|
||||
|
||||
psmouse->protocol_handler = elantech_process_byte;
|
||||
psmouse->disconnect = elantech_disconnect;
|
||||
psmouse->reconnect = elantech_reconnect;
|
||||
psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
|
||||
|
||||
return 0;
|
||||
|
||||
init_fail_tp_reg:
|
||||
input_free_device(tp_dev);
|
||||
init_fail_tp_alloc:
|
||||
sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
|
||||
&elantech_attr_group);
|
||||
init_fail:
|
||||
psmouse_reset(psmouse);
|
||||
kfree(etd);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
#define PACKET_V4_HEAD 0x05
|
||||
#define PACKET_V4_MOTION 0x06
|
||||
#define PACKET_V4_STATUS 0x07
|
||||
#define PACKET_TRACKPOINT 0x08
|
||||
|
||||
/*
|
||||
* track up to 5 fingers for v4 hardware
|
||||
|
@ -114,6 +115,8 @@ struct finger_pos {
|
|||
};
|
||||
|
||||
struct elantech_data {
|
||||
struct input_dev *tp_dev; /* Relative device for trackpoint */
|
||||
char tp_phys[32];
|
||||
unsigned char reg_07;
|
||||
unsigned char reg_10;
|
||||
unsigned char reg_11;
|
||||
|
|
|
@ -17,7 +17,6 @@ static int i8042_aux_irq = -1;
|
|||
#define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
|
||||
|
||||
static void __iomem *kbd_iobase;
|
||||
static struct resource *kbd_res;
|
||||
|
||||
#define I8042_COMMAND_REG (kbd_iobase + 0x64UL)
|
||||
#define I8042_DATA_REG (kbd_iobase + 0x60UL)
|
||||
|
@ -44,6 +43,8 @@ static inline void i8042_write_command(int val)
|
|||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
static struct resource *kbd_res;
|
||||
|
||||
#define OBP_PS2KBD_NAME1 "kb_ps2"
|
||||
#define OBP_PS2KBD_NAME2 "keyboard"
|
||||
#define OBP_PS2MS_NAME1 "kdmouse"
|
||||
|
|
Loading…
Reference in New Issue