input: maxim_sti: add support for multitouch protocol B

Add support for multitouch procotol B, in order to track
object based ID touch activities.

Change-Id: I9b6941b3fea2f5c28434793073330cd4abe9fa74
Signed-off-by: Jigarkumar Kishorkumar Zala <j_zala@codeaurora.org>
This commit is contained in:
Jigarkumar Kishorkumar Zala 2015-10-27 14:32:04 -07:00 committed by David Keitel
parent 6c472a2921
commit d00e0ab13b
2 changed files with 87 additions and 17 deletions

View file

@ -19,7 +19,7 @@ Optional properties:
config defined in pin groups of interrupt and reset gpios.
"pmx_ts_suspend" : disabled configuration of pins. This should specify sleep
config defined in pin groups of interrupt and reset gpios.
- maxim_sti,mt_type_b_enabled : Boolean type. This should be used to enable type B multitouch protocol.
Example:
&spi_13 { /* BLSP1 QUP3 */
@ -38,6 +38,7 @@ Example:
maxim_sti,touch_fusion = "/vendor/bin/touch_fusion";
maxim_sti,config_file = "/vendor/firmware/touch_fusion_panel_id_0x%04x.cfg";
maxim_sti,fw_name = "maxim_fp35.bin";
maxim_sti,mt_type_b_enabled;
pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;

View file

@ -30,6 +30,7 @@
#include <net/genetlink.h>
#include <net/sock.h>
#include <uapi/linux/maxim_sti.h>
#include <linux/input/mt.h>
#include <asm/byteorder.h> /* MUST include this header to get byte order */
#ifdef CONFIG_OF
#include <linux/gpio.h>
@ -76,6 +77,7 @@ struct maxim_sti_pdata {
int (*init)(struct maxim_sti_pdata *pdata, bool init);
void (*reset)(struct maxim_sti_pdata *pdata, int value);
int (*irq)(struct maxim_sti_pdata *pdata);
bool mt_type_b_enabled;
};
struct dev_data;
@ -135,6 +137,8 @@ struct dev_data {
u32 tf_status;
bool idle;
bool gesture_reset;
bool touch_status[INPUT_DEVICES]
[MAX_INPUT_EVENTS];
u16 gesture_en;
unsigned long int sysfs_update_type;
struct completion sysfs_ack_glove;
@ -980,6 +984,9 @@ static int maxim_parse_dt(struct device *dev, struct maxim_sti_pdata *pdata)
pdata->gpio_irq = of_get_named_gpio_flags(np,
"maxim_sti,irq-gpio", 0, &flags);
pdata->mt_type_b_enabled =
of_property_read_bool(np, "maxim_sti,mt_type_b_enabled");
ret = of_property_read_string(np, "maxim_sti,touch_fusion", &str);
if (ret) {
dev_err(dev, "%s: unable to read touch_fusion location (%d)\n",
@ -1108,6 +1115,22 @@ nl_callback_noop(struct sk_buff *skb, struct genl_info *info)
return 0;
}
static void
release_slot_events(struct dev_data *dd, bool *active_touch, int inp)
{
int i;
for (i = 0; i < MAX_INPUT_EVENTS; i++) {
if (dd->touch_status[inp][i] == true &&
active_touch[i] == false) {
input_mt_slot(dd->input_dev[inp], i);
input_mt_report_slot_state(dd->input_dev[inp],
MT_TOOL_FINGER, 0);
}
dd->touch_status[inp][i] = active_touch[i];
}
}
static inline bool
nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
{
@ -1131,9 +1154,10 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
struct dr_sysfs_ack *sysfs_ack_msg;
struct dr_idle *idle_msg;
struct dr_tf_status *tf_status_msg;
u8 i, inp;
int ret;
u8 i, inp;
int ret, id;
u16 read_value[2] = { 0 };
bool active_touch[INPUT_DEVICES][MAX_INPUT_EVENTS] = { {false} };
if (dd->expect_resume_ack && msg_id != DR_DECONFIG &&
msg_id != DR_RESUME_ACK)
@ -1294,6 +1318,19 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
__set_bit(KEY_POWER,
dd->input_dev[i]->keybit);
}
if (pdata->mt_type_b_enabled &&
input_mt_init_slots(dd->input_dev[i],
MAX_INPUT_EVENTS, 0)) {
ERROR("Error in initialising slots\n");
input_free_device(dd->input_dev[i]);
dd->input_dev[i] = NULL;
continue;
} else {
input_set_abs_params(dd->input_dev[i],
ABS_MT_TRACKING_ID, 0,
MAX_INPUT_EVENTS, 0, 0);
}
input_set_abs_params(dd->input_dev[i],
ABS_MT_POSITION_X, 0,
config_input_msg->x_range, 0, 0);
@ -1302,9 +1339,7 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
config_input_msg->y_range, 0, 0);
input_set_abs_params(dd->input_dev[i],
ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
input_set_abs_params(dd->input_dev[i],
ABS_MT_TRACKING_ID, 0,
MAX_INPUT_EVENTS, 0, 0);
if (i == (INPUT_DEVICES - 1))
input_set_abs_params(dd->input_dev[i],
ABS_MT_TOOL_TYPE, 0,
@ -1387,7 +1422,12 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
dd->eraser_active = false;
}
for (i = 0; i < INPUT_DEVICES; i++) {
input_mt_sync(dd->input_dev[i]);
if (pdata->mt_type_b_enabled)
release_slot_events(dd,
active_touch[i], i);
else
input_mt_sync(dd->input_dev[i]);
input_sync(dd->input_dev[i]);
}
} else {
@ -1395,15 +1435,36 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
switch (input_msg->event[i].tool_type) {
case DR_INPUT_FINGER:
inp = 0;
input_report_abs(dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_FINGER);
id = input_msg->event[i].id;
if (pdata->mt_type_b_enabled) {
input_mt_slot(
dd->input_dev[inp], id);
input_mt_report_slot_state(
dd->input_dev[inp],
MT_TOOL_FINGER, 1);
active_touch[inp][id] = true;
} else {
input_report_abs(
dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_FINGER);
}
break;
case DR_INPUT_STYLUS:
inp = INPUT_DEVICES - 1;
input_report_abs(dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_PEN);
if (pdata->mt_type_b_enabled) {
input_mt_slot(
dd->input_dev[inp], id);
input_mt_report_slot_state(
dd->input_dev[inp],
MT_TOOL_PEN, 1);
active_touch[inp][id] = true;
} else {
input_report_abs(
dd->input_dev[inp],
ABS_MT_TOOL_TYPE,
MT_TOOL_PEN);
}
break;
case DR_INPUT_ERASER:
inp = INPUT_DEVICES - 1;
@ -1417,9 +1478,9 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
input_msg->event[i].tool_type);
break;
}
input_report_abs(dd->input_dev[inp],
ABS_MT_TRACKING_ID,
input_msg->event[i].id);
if (!pdata->mt_type_b_enabled)
input_report_abs(dd->input_dev[inp],
ABS_MT_TRACKING_ID, id);
input_report_abs(dd->input_dev[inp],
ABS_MT_POSITION_X,
input_msg->event[i].x);
@ -1429,8 +1490,16 @@ nl_process_driver_msg(struct dev_data *dd, u16 msg_id, void *msg)
input_report_abs(dd->input_dev[inp],
ABS_MT_PRESSURE,
input_msg->event[i].z);
input_mt_sync(dd->input_dev[inp]);
if (!pdata->mt_type_b_enabled)
input_mt_sync(dd->input_dev[inp]);
}
if (pdata->mt_type_b_enabled) {
for (i = 0; i < INPUT_DEVICES; i++)
release_slot_events(dd,
active_touch[i], i);
}
for (i = 0; i < INPUT_DEVICES; i++)
input_sync(dd->input_dev[i]);
}