diff options
author | Roger Quadros <rogerq@ti.com> | 2014-07-28 12:58:54 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-07-28 13:26:17 -0400 |
commit | 62e65b7e85471d54693a4999e36b2632d5648f43 (patch) | |
tree | 64ea4b9500e36303073b597d7153eeacc73794a9 | |
parent | 3808843cf10e4a696d942359d99822eff1a2de8e (diff) |
Input: pixcir_i2c_ts - use Type-B Multi-Touch protocol
Switch to using the Type-B Multi-Touch protocol.
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r-- | drivers/input/touchscreen/pixcir_i2c_ts.c | 125 |
1 files changed, 94 insertions, 31 deletions
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 19c6c0fdc94b..0b016814e6b6 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c | |||
@@ -23,9 +23,12 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/i2c.h> | 24 | #include <linux/i2c.h> |
25 | #include <linux/input.h> | 25 | #include <linux/input.h> |
26 | #include <linux/input/mt.h> | ||
26 | #include <linux/input/pixcir_ts.h> | 27 | #include <linux/input/pixcir_ts.h> |
27 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
28 | 29 | ||
30 | #define PIXCIR_MAX_SLOTS 2 | ||
31 | |||
29 | struct pixcir_i2c_ts_data { | 32 | struct pixcir_i2c_ts_data { |
30 | struct i2c_client *client; | 33 | struct i2c_client *client; |
31 | struct input_dev *input; | 34 | struct input_dev *input; |
@@ -33,12 +36,25 @@ struct pixcir_i2c_ts_data { | |||
33 | bool running; | 36 | bool running; |
34 | }; | 37 | }; |
35 | 38 | ||
36 | static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) | 39 | struct pixcir_touch { |
40 | int x; | ||
41 | int y; | ||
42 | }; | ||
43 | |||
44 | struct pixcir_report_data { | ||
45 | int num_touches; | ||
46 | struct pixcir_touch touches[PIXCIR_MAX_SLOTS]; | ||
47 | }; | ||
48 | |||
49 | static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, | ||
50 | struct pixcir_report_data *report) | ||
37 | { | 51 | { |
38 | struct pixcir_i2c_ts_data *tsdata = data; | ||
39 | u8 rdbuf[10], wrbuf[1] = { 0 }; | 52 | u8 rdbuf[10], wrbuf[1] = { 0 }; |
53 | u8 *bufptr; | ||
40 | u8 touch; | 54 | u8 touch; |
41 | int ret; | 55 | int ret, i; |
56 | |||
57 | memset(report, 0, sizeof(struct pixcir_report_data)); | ||
42 | 58 | ||
43 | ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); | 59 | ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); |
44 | if (ret != sizeof(wrbuf)) { | 60 | if (ret != sizeof(wrbuf)) { |
@@ -56,45 +72,85 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) | |||
56 | return; | 72 | return; |
57 | } | 73 | } |
58 | 74 | ||
59 | touch = rdbuf[0]; | 75 | touch = rdbuf[0] & 0x7; |
60 | if (touch) { | 76 | if (touch > PIXCIR_MAX_SLOTS) |
61 | u16 posx1 = (rdbuf[3] << 8) | rdbuf[2]; | 77 | touch = PIXCIR_MAX_SLOTS; |
62 | u16 posy1 = (rdbuf[5] << 8) | rdbuf[4]; | 78 | |
63 | u16 posx2 = (rdbuf[7] << 8) | rdbuf[6]; | 79 | report->num_touches = touch; |
64 | u16 posy2 = (rdbuf[9] << 8) | rdbuf[8]; | 80 | bufptr = &rdbuf[2]; |
65 | 81 | ||
66 | input_report_key(tsdata->input, BTN_TOUCH, 1); | 82 | for (i = 0; i < touch; i++) { |
67 | input_report_abs(tsdata->input, ABS_X, posx1); | 83 | report->touches[i].x = (bufptr[1] << 8) | bufptr[0]; |
68 | input_report_abs(tsdata->input, ABS_Y, posy1); | 84 | report->touches[i].y = (bufptr[3] << 8) | bufptr[2]; |
69 | 85 | ||
70 | input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1); | 86 | bufptr = bufptr + 4; |
71 | input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1); | ||
72 | input_mt_sync(tsdata->input); | ||
73 | |||
74 | if (touch == 2) { | ||
75 | input_report_abs(tsdata->input, | ||
76 | ABS_MT_POSITION_X, posx2); | ||
77 | input_report_abs(tsdata->input, | ||
78 | ABS_MT_POSITION_Y, posy2); | ||
79 | input_mt_sync(tsdata->input); | ||
80 | } | ||
81 | } else { | ||
82 | input_report_key(tsdata->input, BTN_TOUCH, 0); | ||
83 | } | 87 | } |
88 | } | ||
89 | |||
90 | static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, | ||
91 | struct pixcir_report_data *report) | ||
92 | { | ||
93 | struct input_mt_pos pos[PIXCIR_MAX_SLOTS]; | ||
94 | int slots[PIXCIR_MAX_SLOTS]; | ||
95 | struct pixcir_touch *touch; | ||
96 | int n, i, slot; | ||
97 | struct device *dev = &ts->client->dev; | ||
98 | |||
99 | n = report->num_touches; | ||
100 | if (n > PIXCIR_MAX_SLOTS) | ||
101 | n = PIXCIR_MAX_SLOTS; | ||
84 | 102 | ||
85 | input_sync(tsdata->input); | 103 | for (i = 0; i < n; i++) { |
104 | touch = &report->touches[i]; | ||
105 | pos[i].x = touch->x; | ||
106 | pos[i].y = touch->y; | ||
107 | } | ||
108 | |||
109 | input_mt_assign_slots(ts->input, slots, pos, n); | ||
110 | |||
111 | for (i = 0; i < n; i++) { | ||
112 | touch = &report->touches[i]; | ||
113 | slot = slots[i]; | ||
114 | |||
115 | input_mt_slot(ts->input, slot); | ||
116 | input_mt_report_slot_state(ts->input, | ||
117 | MT_TOOL_FINGER, true); | ||
118 | |||
119 | input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x); | ||
120 | input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y); | ||
121 | |||
122 | dev_dbg(dev, "%d: slot %d, x %d, y %d\n", | ||
123 | i, slot, touch->x, touch->y); | ||
124 | } | ||
125 | |||
126 | input_mt_sync_frame(ts->input); | ||
127 | input_sync(ts->input); | ||
86 | } | 128 | } |
87 | 129 | ||
88 | static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) | 130 | static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) |
89 | { | 131 | { |
90 | struct pixcir_i2c_ts_data *tsdata = dev_id; | 132 | struct pixcir_i2c_ts_data *tsdata = dev_id; |
91 | const struct pixcir_ts_platform_data *pdata = tsdata->chip; | 133 | const struct pixcir_ts_platform_data *pdata = tsdata->chip; |
134 | struct pixcir_report_data report; | ||
92 | 135 | ||
93 | while (tsdata->running) { | 136 | while (tsdata->running) { |
94 | pixcir_ts_poscheck(tsdata); | 137 | /* parse packet */ |
95 | 138 | pixcir_ts_parse(tsdata, &report); | |
96 | if (gpio_get_value(pdata->gpio_attb)) | 139 | |
140 | /* report it */ | ||
141 | pixcir_ts_report(tsdata, &report); | ||
142 | |||
143 | if (gpio_get_value(pdata->gpio_attb)) { | ||
144 | if (report.num_touches) { | ||
145 | /* | ||
146 | * Last report with no finger up? | ||
147 | * Do it now then. | ||
148 | */ | ||
149 | input_mt_sync_frame(tsdata->input); | ||
150 | input_sync(tsdata->input); | ||
151 | } | ||
97 | break; | 152 | break; |
153 | } | ||
98 | 154 | ||
99 | msleep(20); | 155 | msleep(20); |
100 | } | 156 | } |
@@ -371,6 +427,13 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, | |||
371 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); | 427 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); |
372 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); | 428 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); |
373 | 429 | ||
430 | error = input_mt_init_slots(input, PIXCIR_MAX_SLOTS, | ||
431 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
432 | if (error) { | ||
433 | dev_err(dev, "Error initializing Multi-Touch slots\n"); | ||
434 | return error; | ||
435 | } | ||
436 | |||
374 | input_set_drvdata(input, tsdata); | 437 | input_set_drvdata(input, tsdata); |
375 | 438 | ||
376 | error = devm_gpio_request_one(dev, pdata->gpio_attb, | 439 | error = devm_gpio_request_one(dev, pdata->gpio_attb, |