diff options
author | Nick Dyer <nick.dyer@itdev.co.uk> | 2012-08-09 16:13:49 +0100 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:37:49 -0700 |
commit | 203f076d8ef6de9548588b5a89524babceb8712e (patch) | |
tree | 2f9a957a118c4c21f5715c3c868dba33c49390bb /drivers/input/touchscreen/atmel_mxt_ts.c | |
parent | 4cb3cf03ae9bf6add01c2d185df8c7609ead022c (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.c | 92 |
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); |