Commit 36874c7e authored by Roger Quadros's avatar Roger Quadros Committed by Dmitry Torokhov

Input: pixcir_i2c_ts - support up to 5 fingers and hardware tracking IDs

Some variants of the Pixcir touch controller support up to 5 simultaneous
fingers and hardware tracking IDs. Prepare the driver for that.
Signed-off-by: default avatarRoger Quadros <rogerq@ti.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 62e65b7e
...@@ -27,18 +27,20 @@ ...@@ -27,18 +27,20 @@
#include <linux/input/pixcir_ts.h> #include <linux/input/pixcir_ts.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#define PIXCIR_MAX_SLOTS 2 #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */
struct pixcir_i2c_ts_data { struct pixcir_i2c_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
const struct pixcir_ts_platform_data *chip; const struct pixcir_ts_platform_data *pdata;
bool running; bool running;
int max_fingers; /* Max fingers supported in this instance */
}; };
struct pixcir_touch { struct pixcir_touch {
int x; int x;
int y; int y;
int id;
}; };
struct pixcir_report_data { struct pixcir_report_data {
...@@ -49,13 +51,21 @@ struct pixcir_report_data { ...@@ -49,13 +51,21 @@ struct pixcir_report_data {
static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
struct pixcir_report_data *report) struct pixcir_report_data *report)
{ {
u8 rdbuf[10], wrbuf[1] = { 0 }; u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5];
u8 wrbuf[1] = { 0 };
u8 *bufptr; u8 *bufptr;
u8 touch; u8 touch;
int ret, i; int ret, i;
int readsize;
const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip;
memset(report, 0, sizeof(struct pixcir_report_data)); memset(report, 0, sizeof(struct pixcir_report_data));
i = chip->has_hw_ids ? 1 : 0;
readsize = 2 + tsdata->max_fingers * (4 + i);
if (readsize > sizeof(rdbuf))
readsize = sizeof(rdbuf);
ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf));
if (ret != sizeof(wrbuf)) { if (ret != sizeof(wrbuf)) {
dev_err(&tsdata->client->dev, dev_err(&tsdata->client->dev,
...@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, ...@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
return; return;
} }
ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); ret = i2c_master_recv(tsdata->client, rdbuf, readsize);
if (ret != sizeof(rdbuf)) { if (ret != sizeof(rdbuf)) {
dev_err(&tsdata->client->dev, dev_err(&tsdata->client->dev,
"%s: i2c_master_recv failed(), ret=%d\n", "%s: i2c_master_recv failed(), ret=%d\n",
...@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, ...@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
} }
touch = rdbuf[0] & 0x7; touch = rdbuf[0] & 0x7;
if (touch > PIXCIR_MAX_SLOTS) if (touch > tsdata->max_fingers)
touch = PIXCIR_MAX_SLOTS; touch = tsdata->max_fingers;
report->num_touches = touch; report->num_touches = touch;
bufptr = &rdbuf[2]; bufptr = &rdbuf[2];
...@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, ...@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata,
report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; report->touches[i].x = (bufptr[1] << 8) | bufptr[0];
report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; report->touches[i].y = (bufptr[3] << 8) | bufptr[2];
bufptr = bufptr + 4; if (chip->has_hw_ids) {
report->touches[i].id = bufptr[4];
bufptr = bufptr + 5;
} else {
bufptr = bufptr + 4;
}
} }
} }
...@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, ...@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
struct pixcir_touch *touch; struct pixcir_touch *touch;
int n, i, slot; int n, i, slot;
struct device *dev = &ts->client->dev; struct device *dev = &ts->client->dev;
const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip;
n = report->num_touches; n = report->num_touches;
if (n > PIXCIR_MAX_SLOTS) if (n > PIXCIR_MAX_SLOTS)
n = PIXCIR_MAX_SLOTS; n = PIXCIR_MAX_SLOTS;
for (i = 0; i < n; i++) { if (!chip->has_hw_ids) {
touch = &report->touches[i]; for (i = 0; i < n; i++) {
pos[i].x = touch->x; touch = &report->touches[i];
pos[i].y = touch->y; pos[i].x = touch->x;
} pos[i].y = touch->y;
}
input_mt_assign_slots(ts->input, slots, pos, n); input_mt_assign_slots(ts->input, slots, pos, n);
}
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
touch = &report->touches[i]; touch = &report->touches[i];
slot = slots[i];
if (chip->has_hw_ids) {
slot = input_mt_get_slot_by_key(ts->input, touch->id);
if (slot < 0) {
dev_dbg(dev, "no free slot for id 0x%x\n",
touch->id);
continue;
}
} else {
slot = slots[i];
}
input_mt_slot(ts->input, slot); input_mt_slot(ts->input, slot);
input_mt_report_slot_state(ts->input, input_mt_report_slot_state(ts->input,
...@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, ...@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts,
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{ {
struct pixcir_i2c_ts_data *tsdata = dev_id; struct pixcir_i2c_ts_data *tsdata = dev_id;
const struct pixcir_ts_platform_data *pdata = tsdata->chip; const struct pixcir_ts_platform_data *pdata = tsdata->pdata;
struct pixcir_report_data report; struct pixcir_report_data report;
while (tsdata->running) { while (tsdata->running) {
...@@ -399,6 +427,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -399,6 +427,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
if (!pdata->chip.max_fingers) {
dev_err(dev, "Invalid max_fingers in pdata\n");
return -EINVAL;
}
tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
if (!tsdata) if (!tsdata)
return -ENOMEM; return -ENOMEM;
...@@ -411,7 +444,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -411,7 +444,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
tsdata->client = client; tsdata->client = client;
tsdata->input = input; tsdata->input = input;
tsdata->chip = pdata; tsdata->pdata = pdata;
input->name = client->name; input->name = client->name;
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
...@@ -427,7 +460,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -427,7 +460,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS, tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
tsdata->max_fingers = PIXCIR_MAX_SLOTS;
dev_info(dev, "Limiting maximum fingers to %d\n",
tsdata->max_fingers);
}
error = input_mt_init_slots(input, tsdata->max_fingers,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
if (error) { if (error) {
dev_err(dev, "Error initializing Multi-Touch slots\n"); dev_err(dev, "Error initializing Multi-Touch slots\n");
......
...@@ -43,10 +43,22 @@ enum pixcir_int_mode { ...@@ -43,10 +43,22 @@ enum pixcir_int_mode {
#define PIXCIR_INT_ENABLE (1UL << 3) #define PIXCIR_INT_ENABLE (1UL << 3)
#define PIXCIR_INT_POL_HIGH (1UL << 2) #define PIXCIR_INT_POL_HIGH (1UL << 2)
/**
* struct pixcir_irc_chip_data - chip related data
* @max_fingers: Max number of fingers reported simultaneously by h/w
* @has_hw_ids: Hardware supports finger tracking IDs
*
*/
struct pixcir_i2c_chip_data {
u8 max_fingers;
bool has_hw_ids;
};
struct pixcir_ts_platform_data { struct pixcir_ts_platform_data {
int x_max; int x_max;
int y_max; int y_max;
int gpio_attb; /* GPIO connected to ATTB line */ int gpio_attb; /* GPIO connected to ATTB line */
struct pixcir_i2c_chip_data chip;
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment