Skip to content

Commit 5f47814

Browse files
committed
input: Add support for Intel Precise Touch & Stylus
Signed-off-by: Dorian Stoll <dorian.stoll@tmsp.io>
1 parent 9c75074 commit 5f47814

29 files changed

+1588
-0
lines changed

drivers/input/touchscreen/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,4 +1310,6 @@ config TOUCHSCREEN_IQS5XX
13101310
To compile this driver as a module, choose M here: the
13111311
module will be called iqs5xx.
13121312

1313+
source "drivers/input/touchscreen/ipts/Kconfig"
1314+
13131315
endif

drivers/input/touchscreen/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o
4545
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
4646
obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
4747
obj-$(CONFIG_TOUCHSCREEN_HIDEEP) += hideep.o
48+
obj-$(CONFIG_TOUCHSCREEN_IPTS) += ipts/
4849
obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
4950
obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
5051
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
config TOUCHSCREEN_IPTS
4+
tristate "Intel Precise Touch & Stylus"
5+
select INTEL_MEI
6+
depends on X86
7+
depends on PCI
8+
depends on HID
9+
help
10+
Say Y here if your system has a touchscreen using Intels
11+
Precise Touch & Stylus (IPTS).
12+
13+
If unsure say N.
14+
15+
To compile this driver as a module, choose M here: the
16+
module will be called ipts.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
#
3+
# Makefile for the IPTS touchscreen driver
4+
#
5+
6+
obj-$(CONFIG_TOUCHSCREEN_IPTS) += ipts.o
7+
ipts-objs := control.o
8+
ipts-objs += devices.o
9+
ipts-objs += hid.o
10+
ipts-objs += init.o
11+
ipts-objs += math.o
12+
ipts-objs += params.o
13+
ipts-objs += receiver.o
14+
ipts-objs += resources.o
15+
ipts-objs += singletouch.o
16+
ipts-objs += stylus.o
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
3+
#ifndef _IPTS_CONTEXT_H_
4+
#define _IPTS_CONTEXT_H_
5+
6+
#include <linux/kthread.h>
7+
#include <linux/input.h>
8+
#include <linux/mei_cl_bus.h>
9+
#include <linux/types.h>
10+
11+
#include "devices.h"
12+
#include "protocol/enums.h"
13+
#include "protocol/responses.h"
14+
15+
/*
16+
* IPTS driver states
17+
*/
18+
enum ipts_host_status {
19+
IPTS_HOST_STATUS_NONE,
20+
IPTS_HOST_STATUS_INIT,
21+
IPTS_HOST_STATUS_RESOURCE_READY,
22+
IPTS_HOST_STATUS_STARTED,
23+
IPTS_HOST_STATUS_STOPPING,
24+
IPTS_HOST_STATUS_RESTARTING
25+
};
26+
27+
struct ipts_buffer_info {
28+
u32 size;
29+
u8 *address;
30+
dma_addr_t dma_address;
31+
};
32+
33+
struct ipts_context {
34+
struct mei_cl_device *client_dev;
35+
struct device *dev;
36+
struct ipts_device_info device_info;
37+
struct ipts_device_config device_cfg;
38+
39+
enum ipts_host_status status;
40+
enum ipts_sensor_mode mode;
41+
42+
struct ipts_buffer_info touch_data[16];
43+
struct ipts_buffer_info feedback[16];
44+
struct ipts_buffer_info doorbell;
45+
46+
/*
47+
* These buffers are not actually used by anything, but they need
48+
* to be allocated and passed to the ME to get proper functionality.
49+
*/
50+
struct ipts_buffer_info workqueue;
51+
struct ipts_buffer_info host2me;
52+
53+
struct task_struct *receiver_loop;
54+
struct task_struct *hid_loop;
55+
56+
struct input_dev *stylus;
57+
struct input_dev *singletouch;
58+
u16 stylus_tool;
59+
};
60+
61+
#endif /* _IPTS_CONTEXT_H_ */
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
#include <linux/mei_cl_bus.h>
4+
#include <linux/types.h>
5+
6+
#include "context.h"
7+
#include "params.h"
8+
#include "protocol/commands.h"
9+
#include "protocol/enums.h"
10+
#include "protocol/events.h"
11+
#include "protocol/touch.h"
12+
#include "resources.h"
13+
14+
int ipts_control_send(struct ipts_context *ipts,
15+
u32 cmd, void *data, u32 size)
16+
{
17+
int ret;
18+
struct ipts_command msg;
19+
20+
memset(&msg, 0, sizeof(struct ipts_command));
21+
msg.code = cmd;
22+
23+
// Copy message payload
24+
if (data && size > 0)
25+
memcpy(&msg.data, data, size);
26+
27+
ret = mei_cldev_send(ipts->client_dev, (u8 *)&msg,
28+
sizeof(msg.code) + size);
29+
if (ret < 0) {
30+
dev_err(ipts->dev, "%s: error 0x%X:%d\n", __func__, cmd, ret);
31+
return ret;
32+
}
33+
34+
return 0;
35+
}
36+
37+
int ipts_control_send_feedback(struct ipts_context *ipts,
38+
u32 buffer, u32 transaction)
39+
{
40+
struct ipts_buffer_info feedback_buffer;
41+
struct ipts_feedback *feedback;
42+
struct ipts_feedback_cmd cmd;
43+
44+
feedback_buffer = ipts->feedback[buffer];
45+
feedback = (struct ipts_feedback *)feedback_buffer.address;
46+
47+
memset(feedback, 0, sizeof(struct ipts_feedback));
48+
memset(&cmd, 0, sizeof(struct ipts_feedback_cmd));
49+
50+
feedback->type = IPTS_FEEDBACK_TYPE_NONE;
51+
feedback->transaction = transaction;
52+
53+
cmd.buffer = buffer;
54+
cmd.transaction = transaction;
55+
56+
return ipts_control_send(ipts, IPTS_CMD(FEEDBACK),
57+
&cmd, sizeof(struct ipts_feedback_cmd));
58+
}
59+
60+
int ipts_control_start(struct ipts_context *ipts)
61+
{
62+
ipts->status = IPTS_HOST_STATUS_INIT;
63+
64+
if (ipts_params.singletouch)
65+
ipts->mode = IPTS_SENSOR_MODE_SINGLETOUCH;
66+
else
67+
ipts->mode = IPTS_SENSOR_MODE_MULTITOUCH;
68+
69+
return ipts_control_send(ipts, IPTS_CMD(NOTIFY_DEV_READY), NULL, 0);
70+
}
71+
72+
void ipts_control_stop(struct ipts_context *ipts)
73+
{
74+
enum ipts_host_status old_status = ipts->status;
75+
76+
ipts->status = IPTS_HOST_STATUS_STOPPING;
77+
ipts_control_send(ipts, IPTS_CMD(QUIESCE_IO), NULL, 0);
78+
ipts_control_send(ipts, IPTS_CMD(CLEAR_MEM_WINDOW), NULL, 0);
79+
80+
if (old_status < IPTS_HOST_STATUS_RESOURCE_READY)
81+
return;
82+
83+
ipts_resources_free(ipts);
84+
}
85+
86+
int ipts_control_restart(struct ipts_context *ipts)
87+
{
88+
dev_info(ipts->dev, "Restarting IPTS\n");
89+
ipts_control_stop(ipts);
90+
91+
ipts->status = IPTS_HOST_STATUS_RESTARTING;
92+
return ipts_control_send(ipts, IPTS_CMD(QUIESCE_IO), NULL, 0);
93+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
3+
#ifndef _IPTS_CONTROL_H_
4+
#define _IPTS_CONTROL_H_
5+
6+
#include <linux/types.h>
7+
8+
#include "context.h"
9+
10+
int ipts_control_start(struct ipts_context *ipts);
11+
void ipts_control_stop(struct ipts_context *ipts);
12+
int ipts_control_restart(struct ipts_context *ipts);
13+
int ipts_control_send(struct ipts_context *ipts,
14+
u32 cmd, void *data, u32 size);
15+
int ipts_control_send_feedback(struct ipts_context *ipts,
16+
u32 buffer, u32 transaction);
17+
18+
#endif /* _IPTS_CONTROL_H_ */
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
#include <linux/kernel.h>
4+
#include <linux/types.h>
5+
6+
#include "devices.h"
7+
8+
static const struct ipts_device_config ipts_devices[] = {
9+
{
10+
.vendor_id = 0x1B96,
11+
.device_id = 0x006A,
12+
.max_stylus_pressure = 1024,
13+
.stylus_protocol = IPTS_STYLUS_PROTOCOL_GEN1,
14+
},
15+
{
16+
.vendor_id = 0x1B96,
17+
.device_id = 0x005e,
18+
.max_stylus_pressure = 1024,
19+
.stylus_protocol = IPTS_STYLUS_PROTOCOL_GEN1,
20+
},
21+
};
22+
23+
struct ipts_device_config ipts_devices_get_config(u32 vendor, u32 device)
24+
{
25+
int i;
26+
struct ipts_device_config cfg;
27+
28+
for (i = 0; i < ARRAY_SIZE(ipts_devices); i++) {
29+
cfg = ipts_devices[i];
30+
31+
if (cfg.vendor_id != vendor)
32+
continue;
33+
if (cfg.device_id != device)
34+
continue;
35+
36+
return cfg;
37+
}
38+
39+
// No device was found, so return a default config
40+
cfg.vendor_id = vendor;
41+
cfg.device_id = device;
42+
cfg.max_stylus_pressure = 4096;
43+
cfg.stylus_protocol = IPTS_STYLUS_PROTOCOL_GEN2;
44+
45+
return cfg;
46+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
3+
#ifndef _IPTS_DEVICES_H_
4+
#define _IPTS_DEVICES_H_
5+
6+
#include <linux/types.h>
7+
8+
/*
9+
* These names describe the different iterations of the IPTS stylus protocol.
10+
*
11+
* IPTS_STYLUS_PROTOCOL_GEN1 can be found on devices that don't have
12+
* support for tilt, and only 1024 pressure levels. (Using NTRIG digitizers)
13+
*
14+
* IPTS_STYLUS_PROTOCOL_GEN2 can be found on devices that support tilting
15+
* the stylus, with 4096 levels of pressure. (Using MS digitizers)
16+
*
17+
* New generations have to be added as they are discovered.
18+
*/
19+
enum ipts_stylus_protocol {
20+
IPTS_STYLUS_PROTOCOL_GEN1,
21+
IPTS_STYLUS_PROTOCOL_GEN2
22+
};
23+
24+
struct ipts_device_config {
25+
u32 vendor_id;
26+
u32 device_id;
27+
u32 max_stylus_pressure;
28+
enum ipts_stylus_protocol stylus_protocol;
29+
};
30+
31+
struct ipts_device_config ipts_devices_get_config(u32 vendor, u32 device);
32+
33+
#endif /* _IPTS_DEVICES_H_ */

0 commit comments

Comments
 (0)