|
@@ -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 {
|
|
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,
|
|
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,
|
|
}
|
|
}
|
|
|
|
|
|
touch = rdbuf[0] & 0x7;
|
|
touch = rdbuf[0] & 0x7;
|
|
- if (touch > PIXCIR_MAX_SLOTS)
|
|
|
|
- touch = PIXCIR_MAX_SLOTS;
|
|
|
|
|
|
+ if (touch > tsdata->max_fingers)
|
|
|
|
+ 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,
|
|
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,
|
|
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++) {
|
|
|
|
- touch = &report->touches[i];
|
|
|
|
- pos[i].x = touch->x;
|
|
|
|
- pos[i].y = touch->y;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!chip->has_hw_ids) {
|
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
|
+ touch = &report->touches[i];
|
|
|
|
+ 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,
|
|
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,
|
|
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,
|
|
|
|
|
|
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,
|
|
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");
|