diff options
-rw-r--r-- | drivers/input/touchscreen/pixcir_i2c_ts.c | 74 | ||||
-rw-r--r-- | include/linux/input/pixcir_ts.h | 12 |
2 files changed, 69 insertions, 17 deletions
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 0b016814e6b6..eddda520a1a7 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
@@ -27,18 +27,20 @@ | |||
27 | #include <linux/input/pixcir_ts.h> | 27 | #include <linux/input/pixcir_ts.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | 29 | ||
30 | #define PIXCIR_MAX_SLOTS 2 | 30 | #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ |
31 | 31 | ||
32 | struct pixcir_i2c_ts_data { | 32 | struct pixcir_i2c_ts_data { |
33 | struct i2c_client *client; | 33 | struct i2c_client *client; |
34 | struct input_dev *input; | 34 | struct input_dev *input; |
35 | const struct pixcir_ts_platform_data *chip; | 35 | const struct pixcir_ts_platform_data *pdata; |
36 | bool running; | 36 | bool running; |
37 | int max_fingers; /* Max fingers supported in this instance */ | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | struct pixcir_touch { | 40 | struct pixcir_touch { |
40 | int x; | 41 | int x; |
41 | int y; | 42 | int y; |
43 | int id; | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct pixcir_report_data { | 46 | struct pixcir_report_data { |
@@ -49,13 +51,21 @@ struct pixcir_report_data { | |||
49 | static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | 51 | static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, |
50 | struct pixcir_report_data *report) | 52 | struct pixcir_report_data *report) |
51 | { | 53 | { |
52 | u8 rdbuf[10], wrbuf[1] = { 0 }; | 54 | u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5]; |
55 | u8 wrbuf[1] = { 0 }; | ||
53 | u8 *bufptr; | 56 | u8 *bufptr; |
54 | u8 touch; | 57 | u8 touch; |
55 | int ret, i; | 58 | int ret, i; |
59 | int readsize; | ||
60 | const struct pixcir_i2c_chip_data *chip = &tsdata->pdata->chip; | ||
56 | 61 | ||
57 | memset(report, 0, sizeof(struct pixcir_report_data)); | 62 | memset(report, 0, sizeof(struct pixcir_report_data)); |
58 | 63 | ||
64 | i = chip->has_hw_ids ? 1 : 0; | ||
65 | readsize = 2 + tsdata->max_fingers * (4 + i); | ||
66 | if (readsize > sizeof(rdbuf)) | ||
67 | readsize = sizeof(rdbuf); | ||
68 | |||
59 | ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); | 69 | ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); |
60 | if (ret != sizeof(wrbuf)) { | 70 | if (ret != sizeof(wrbuf)) { |
61 | dev_err(&tsdata->client->dev, | 71 | dev_err(&tsdata->client->dev, |
@@ -64,7 +74,7 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | |||
64 | return; | 74 | return; |
65 | } | 75 | } |
66 | 76 | ||
67 | ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); | 77 | ret = i2c_master_recv(tsdata->client, rdbuf, readsize); |
68 | if (ret != sizeof(rdbuf)) { | 78 | if (ret != sizeof(rdbuf)) { |
69 | dev_err(&tsdata->client->dev, | 79 | dev_err(&tsdata->client->dev, |
70 | "%s: i2c_master_recv failed(), ret=%d\n", | 80 | "%s: i2c_master_recv failed(), ret=%d\n", |
@@ -73,8 +83,8 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | |||
73 | } | 83 | } |
74 | 84 | ||
75 | touch = rdbuf[0] & 0x7; | 85 | touch = rdbuf[0] & 0x7; |
76 | if (touch > PIXCIR_MAX_SLOTS) | 86 | if (touch > tsdata->max_fingers) |
77 | touch = PIXCIR_MAX_SLOTS; | 87 | touch = tsdata->max_fingers; |
78 | 88 | ||
79 | report->num_touches = touch; | 89 | report->num_touches = touch; |
80 | bufptr = &rdbuf[2]; | 90 | bufptr = &rdbuf[2]; |
@@ -83,7 +93,12 @@ static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | |||
83 | report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; | 93 | report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; |
84 | report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; | 94 | report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; |
85 | 95 | ||
86 | bufptr = bufptr + 4; | 96 | if (chip->has_hw_ids) { |
97 | report->touches[i].id = bufptr[4]; | ||
98 | bufptr = bufptr + 5; | ||
99 | } else { | ||
100 | bufptr = bufptr + 4; | ||
101 | } | ||
87 | } | 102 | } |
88 | } | 103 | } |
89 | 104 | ||
@@ -95,22 +110,35 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | |||
95 | struct pixcir_touch *touch; | 110 | struct pixcir_touch *touch; |
96 | int n, i, slot; | 111 | int n, i, slot; |
97 | struct device *dev = &ts->client->dev; | 112 | struct device *dev = &ts->client->dev; |
113 | const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip; | ||
98 | 114 | ||
99 | n = report->num_touches; | 115 | n = report->num_touches; |
100 | if (n > PIXCIR_MAX_SLOTS) | 116 | if (n > PIXCIR_MAX_SLOTS) |
101 | n = PIXCIR_MAX_SLOTS; | 117 | n = PIXCIR_MAX_SLOTS; |
102 | 118 | ||
103 | for (i = 0; i < n; i++) { | 119 | if (!chip->has_hw_ids) { |
104 | touch = &report->touches[i]; | 120 | for (i = 0; i < n; i++) { |
105 | pos[i].x = touch->x; | 121 | touch = &report->touches[i]; |
106 | pos[i].y = touch->y; | 122 | pos[i].x = touch->x; |
107 | } | 123 | pos[i].y = touch->y; |
124 | } | ||
108 | 125 | ||
109 | input_mt_assign_slots(ts->input, slots, pos, n); | 126 | input_mt_assign_slots(ts->input, slots, pos, n); |
127 | } | ||
110 | 128 | ||
111 | for (i = 0; i < n; i++) { | 129 | for (i = 0; i < n; i++) { |
112 | touch = &report->touches[i]; | 130 | touch = &report->touches[i]; |
113 | slot = slots[i]; | 131 | |
132 | if (chip->has_hw_ids) { | ||
133 | slot = input_mt_get_slot_by_key(ts->input, touch->id); | ||
134 | if (slot < 0) { | ||
135 | dev_dbg(dev, "no free slot for id 0x%x\n", | ||
136 | touch->id); | ||
137 | continue; | ||
138 | } | ||
139 | } else { | ||
140 | slot = slots[i]; | ||
141 | } | ||
114 | 142 | ||
115 | input_mt_slot(ts->input, slot); | 143 | input_mt_slot(ts->input, slot); |
116 | input_mt_report_slot_state(ts->input, | 144 | input_mt_report_slot_state(ts->input, |
@@ -130,7 +158,7 @@ static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | |||
130 | static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) | 158 | static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) |
131 | { | 159 | { |
132 | struct pixcir_i2c_ts_data *tsdata = dev_id; | 160 | struct pixcir_i2c_ts_data *tsdata = dev_id; |
133 | const struct pixcir_ts_platform_data *pdata = tsdata->chip; | 161 | const struct pixcir_ts_platform_data *pdata = tsdata->pdata; |
134 | struct pixcir_report_data report; | 162 | struct pixcir_report_data report; |
135 | 163 | ||
136 | while (tsdata->running) { | 164 | while (tsdata->running) { |
@@ -399,6 +427,11 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, | |||
399 | return -EINVAL; | 427 | return -EINVAL; |
400 | } | 428 | } |
401 | 429 | ||
430 | if (!pdata->chip.max_fingers) { | ||
431 | dev_err(dev, "Invalid max_fingers in pdata\n"); | ||
432 | return -EINVAL; | ||
433 | } | ||
434 | |||
402 | tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); | 435 | tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); |
403 | if (!tsdata) | 436 | if (!tsdata) |
404 | return -ENOMEM; | 437 | return -ENOMEM; |
@@ -411,7 +444,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, | |||
411 | 444 | ||
412 | tsdata->client = client; | 445 | tsdata->client = client; |
413 | tsdata->input = input; | 446 | tsdata->input = input; |
414 | tsdata->chip = pdata; | 447 | tsdata->pdata = pdata; |
415 | 448 | ||
416 | input->name = client->name; | 449 | input->name = client->name; |
417 | input->id.bustype = BUS_I2C; | 450 | input->id.bustype = BUS_I2C; |
@@ -427,7 +460,14 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, | |||
427 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); | 460 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); |
428 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); | 461 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); |
429 | 462 | ||
430 | error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS, | 463 | tsdata->max_fingers = tsdata->pdata->chip.max_fingers; |
464 | if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) { | ||
465 | tsdata->max_fingers = PIXCIR_MAX_SLOTS; | ||
466 | dev_info(dev, "Limiting maximum fingers to %d\n", | ||
467 | tsdata->max_fingers); | ||
468 | } | ||
469 | |||
470 | error = input_mt_init_slots(input, tsdata->max_fingers, | ||
431 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | 471 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
432 | if (error) { | 472 | if (error) { |
433 | dev_err(dev, "Error initializing Multi-Touch slots\n"); | 473 | dev_err(dev, "Error initializing Multi-Touch slots\n"); |
diff --git a/include/linux/input/pixcir_ts.h b/include/linux/input/pixcir_ts.h index 160cf353aa39..7bae83b7c396 100644 --- a/include/linux/input/pixcir_ts.h +++ b/include/linux/input/pixcir_ts.h | |||
@@ -43,10 +43,22 @@ enum pixcir_int_mode { | |||
43 | #define PIXCIR_INT_ENABLE (1UL << 3) | 43 | #define PIXCIR_INT_ENABLE (1UL << 3) |
44 | #define PIXCIR_INT_POL_HIGH (1UL << 2) | 44 | #define PIXCIR_INT_POL_HIGH (1UL << 2) |
45 | 45 | ||
46 | /** | ||
47 | * struct pixcir_irc_chip_data - chip related data | ||
48 | * @max_fingers: Max number of fingers reported simultaneously by h/w | ||
49 | * @has_hw_ids: Hardware supports finger tracking IDs | ||
50 | * | ||
51 | */ | ||
52 | struct pixcir_i2c_chip_data { | ||
53 | u8 max_fingers; | ||
54 | bool has_hw_ids; | ||
55 | }; | ||
56 | |||
46 | struct pixcir_ts_platform_data { | 57 | struct pixcir_ts_platform_data { |
47 | int x_max; | 58 | int x_max; |
48 | int y_max; | 59 | int y_max; |
49 | int gpio_attb; /* GPIO connected to ATTB line */ | 60 | int gpio_attb; /* GPIO connected to ATTB line */ |
61 | struct pixcir_i2c_chip_data chip; | ||
50 | }; | 62 | }; |
51 | 63 | ||
52 | #endif | 64 | #endif |