summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/atmel_mxt_ts.c
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2012-08-09 16:13:49 +0100
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:37:49 -0700
commit203f076d8ef6de9548588b5a89524babceb8712e (patch)
tree2f9a957a118c4c21f5715c3c868dba33c49390bb /drivers/input/touchscreen/atmel_mxt_ts.c
parent4cb3cf03ae9bf6add01c2d185df8c7609ead022c (diff)
Input: atmel_mxt_ts - Implement T63 Active Stylus support
Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Rebase-Id: R0c213dfd9d726b99023035333a34c42f7c940595
Diffstat (limited to 'drivers/input/touchscreen/atmel_mxt_ts.c')
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c92
1 files changed, 91 insertions, 1 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4fa6b9a7eb28..028c67f439aa 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -62,6 +62,7 @@
#define MXT_TOUCH_PROXKEY_T52 52
#define MXT_PROCI_GRIPFACE_T20 20
#define MXT_PROCG_NOISE_T22 22
+#define MXT_PROCI_ACTIVE_STYLUS_T63 63
#define MXT_PROCI_ONETOUCH_T24 24
#define MXT_PROCI_TWOTOUCH_T27 27
#define MXT_PROCI_GRIP_T40 40
@@ -234,6 +235,19 @@
#define MXT_X_INVERT (1 << 1)
#define MXT_Y_INVERT (1 << 2)
+/* T63 Stylus */
+#define MXT_STYLUS_PRESS (1 << 0)
+#define MXT_STYLUS_RELEASE (1 << 1)
+#define MXT_STYLUS_MOVE (1 << 2)
+#define MXT_STYLUS_SUPPRESS (1 << 3)
+
+#define MXT_STYLUS_DETECT (1 << 4)
+#define MXT_STYLUS_TIP (1 << 5)
+#define MXT_STYLUS_ERASER (1 << 6)
+#define MXT_STYLUS_BARREL (1 << 7)
+
+#define MXT_STYLUS_PRESSURE_MASK 0x3F
+
/* Touchscreen absolute values */
#define MXT_MAX_AREA 0xff
@@ -289,6 +303,7 @@ struct mxt_data {
u32 config_crc;
u32 info_block_crc;
u8 num_touchids;
+ u8 num_stylusids;
u8 *msg_buf;
u8 last_message_count;
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -306,6 +321,8 @@ struct mxt_data {
u8 T42_reportid_max;
u16 T44_address;
u8 T48_reportid;
+ u8 T63_reportid_min;
+ u8 T63_reportid_max;
};
/* I2C slave address pairs */
@@ -788,6 +805,60 @@ static int mxt_proc_t48_messages(struct mxt_data *data, u8 *msg)
return 0;
}
+static void mxt_proc_t63_messages(struct mxt_data *data, u8 *msg)
+{
+ struct device *dev = &data->client->dev;
+ struct input_dev *input_dev = data->input_dev;
+ u8 id;
+ u16 x, y;
+ u8 pressure;
+
+ if (!input_dev)
+ return;
+
+ /* stylus slots come after touch slots */
+ id = data->num_touchids + (msg[0] - data->T63_reportid_min);
+
+ if (id < 0 || id > (data->num_touchids + data->num_stylusids)) {
+ dev_err(dev, "invalid stylus id %d, max slot is %d\n",
+ id, data->num_stylusids);
+ return;
+ }
+
+ x = msg[3] | (msg[4] << 8);
+ y = msg[5] | (msg[6] << 8);
+ pressure = msg[7] & MXT_STYLUS_PRESSURE_MASK;
+
+ dev_dbg(dev,
+ "[%d] %c%c%c%c x: %d y: %d pressure: %d stylus:%c%c%c%c\n",
+ id,
+ (msg[1] & MXT_STYLUS_SUPPRESS) ? 'S' : '.',
+ (msg[1] & MXT_STYLUS_MOVE) ? 'M' : '.',
+ (msg[1] & MXT_STYLUS_RELEASE) ? 'R' : '.',
+ (msg[1] & MXT_STYLUS_PRESS) ? 'P' : '.',
+ x, y, pressure,
+ (msg[2] & MXT_STYLUS_BARREL) ? 'B' : '.',
+ (msg[2] & MXT_STYLUS_ERASER) ? 'E' : '.',
+ (msg[2] & MXT_STYLUS_TIP) ? 'T' : '.',
+ (msg[2] & MXT_STYLUS_DETECT) ? 'D' : '.');
+
+ input_mt_slot(input_dev, id);
+
+ if (msg[2] & MXT_STYLUS_DETECT) {
+ input_mt_report_slot_state(input_dev, MT_TOOL_PEN, 1);
+ input_report_abs(input_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
+ } else {
+ input_mt_report_slot_state(input_dev, MT_TOOL_PEN, 0);
+ }
+
+ input_report_key(input_dev, BTN_STYLUS, (msg[2] & MXT_STYLUS_ERASER));
+ input_report_key(input_dev, BTN_STYLUS2, (msg[2] & MXT_STYLUS_BARREL));
+
+ mxt_input_sync(data);
+}
+
static int mxt_proc_message(struct mxt_data *data, u8 *msg)
{
u8 report_id = msg[0];
@@ -802,6 +873,9 @@ static int mxt_proc_message(struct mxt_data *data, u8 *msg)
if (report_id >= data->T9_reportid_min
&& report_id <= data->T9_reportid_max) {
mxt_proc_t9_messages(data, msg);
+ } else if (report_id >= data->T63_reportid_min
+ && report_id <= data->T63_reportid_max) {
+ mxt_proc_t63_messages(data, msg);
} else if (report_id == data->T6_reportid) {
mxt_proc_t6_messages(data, msg);
} else if (report_id == data->T48_reportid) {
@@ -1477,6 +1551,12 @@ static int mxt_get_object_table(struct mxt_data *data)
case MXT_SPT_NOISESUPPRESSION_T48:
data->T48_reportid = object->max_reportid;
break;
+ case MXT_PROCI_ACTIVE_STYLUS_T63:
+ data->T63_reportid_max = object->max_reportid;
+ data->T63_reportid_min = object->min_reportid;
+ data->num_stylusids =
+ object->num_report_ids * object->instances;
+ break;
}
dev_dbg(dev, "T%u, start:%u size:%u instances:%u "
@@ -2028,7 +2108,8 @@ static int mxt_initialize_input_device(struct mxt_data *data)
0, 255, 0, 0);
/* For multi touch */
- input_mt_init_slots(input_dev, data->num_touchids, 0);
+ input_mt_init_slots(input_dev,
+ data->num_touchids + data->num_stylusids, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MXT_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
@@ -2040,6 +2121,15 @@ static int mxt_initialize_input_device(struct mxt_data *data)
input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
0, 255, 0, 0);
+ /* For T63 active stylus */
+ if (data->T63_reportid_min) {
+ __set_bit(BTN_STYLUS, input_dev->keybit);
+ __set_bit(BTN_STYLUS2, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+ 0, MT_TOOL_MAX, 0, 0);
+ }
+
input_set_drvdata(input_dev, data);
i2c_set_clientdata(data->client, data);