Commit 7ccc4359be6d2c42e064ca03ea997e13aa8d7cce
Committed by
Sekhar Nori
1 parent
61801fcf75
Exists in
ti-linux-3.14.y
and in
2 other branches
Input: edt-ft5x06 - add support for M09 firmware version
[ Upstream commit fd335ab04b3f1b3309dfbfea71a1a79a7bacc4ad ] There is a new firmware version for the EDT-FT5x06 chip. Add support for detecting the firmware version and handle the differences appropriately. Signed-off-by: Lothar Waßmann <LW@KARO-electronics.de> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Showing 1 changed file with 276 additions and 82 deletions Side-by-side Diff
drivers/input/touchscreen/edt-ft5x06.c
1 | 1 | /* |
2 | 2 | * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> |
3 | + * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support) | |
3 | 4 | * Lothar Waßmann <LW@KARO-electronics.de> (DT support) |
4 | 5 | * |
5 | 6 | * This software is licensed under the terms of the GNU General Public |
... | ... | @@ -47,6 +48,14 @@ |
47 | 48 | #define WORK_REGISTER_NUM_X 0x33 |
48 | 49 | #define WORK_REGISTER_NUM_Y 0x34 |
49 | 50 | |
51 | +#define M09_REGISTER_THRESHOLD 0x80 | |
52 | +#define M09_REGISTER_GAIN 0x92 | |
53 | +#define M09_REGISTER_OFFSET 0x93 | |
54 | +#define M09_REGISTER_NUM_X 0x94 | |
55 | +#define M09_REGISTER_NUM_Y 0x95 | |
56 | + | |
57 | +#define NO_REGISTER 0xff | |
58 | + | |
50 | 59 | #define WORK_REGISTER_OPMODE 0x3c |
51 | 60 | #define FACTORY_REGISTER_OPMODE 0x01 |
52 | 61 | |
... | ... | @@ -61,6 +70,20 @@ |
61 | 70 | #define EDT_RAW_DATA_RETRIES 100 |
62 | 71 | #define EDT_RAW_DATA_DELAY 1 /* msec */ |
63 | 72 | |
73 | +enum edt_ver { | |
74 | + M06, | |
75 | + M09, | |
76 | +}; | |
77 | + | |
78 | +struct edt_reg_addr { | |
79 | + int reg_threshold; | |
80 | + int reg_report_rate; | |
81 | + int reg_gain; | |
82 | + int reg_offset; | |
83 | + int reg_num_x; | |
84 | + int reg_num_y; | |
85 | +}; | |
86 | + | |
64 | 87 | struct edt_ft5x06_ts_data { |
65 | 88 | struct i2c_client *client; |
66 | 89 | struct input_dev *input; |
... | ... | @@ -85,6 +108,9 @@ |
85 | 108 | int report_rate; |
86 | 109 | |
87 | 110 | char name[EDT_NAME_LEN]; |
111 | + | |
112 | + struct edt_reg_addr reg_addr; | |
113 | + enum edt_ver version; | |
88 | 114 | }; |
89 | 115 | |
90 | 116 | static int edt_ft5x06_ts_readwrite(struct i2c_client *client, |
91 | 117 | |
92 | 118 | |
93 | 119 | |
94 | 120 | |
95 | 121 | |
96 | 122 | |
... | ... | @@ -142,33 +168,58 @@ |
142 | 168 | { |
143 | 169 | struct edt_ft5x06_ts_data *tsdata = dev_id; |
144 | 170 | struct device *dev = &tsdata->client->dev; |
145 | - u8 cmd = 0xf9; | |
146 | - u8 rdbuf[26]; | |
171 | + u8 cmd; | |
172 | + u8 rdbuf[29]; | |
147 | 173 | int i, type, x, y, id; |
174 | + int offset, tplen, datalen; | |
148 | 175 | int error; |
149 | 176 | |
177 | + switch (tsdata->version) { | |
178 | + case M06: | |
179 | + cmd = 0xf9; /* tell the controller to send touch data */ | |
180 | + offset = 5; /* where the actual touch data starts */ | |
181 | + tplen = 4; /* data comes in so called frames */ | |
182 | + datalen = 26; /* how much bytes to listen for */ | |
183 | + break; | |
184 | + | |
185 | + case M09: | |
186 | + cmd = 0x02; | |
187 | + offset = 1; | |
188 | + tplen = 6; | |
189 | + datalen = 29; | |
190 | + break; | |
191 | + | |
192 | + default: | |
193 | + goto out; | |
194 | + } | |
195 | + | |
150 | 196 | memset(rdbuf, 0, sizeof(rdbuf)); |
151 | 197 | |
152 | 198 | error = edt_ft5x06_ts_readwrite(tsdata->client, |
153 | 199 | sizeof(cmd), &cmd, |
154 | - sizeof(rdbuf), rdbuf); | |
200 | + datalen, rdbuf); | |
155 | 201 | if (error) { |
156 | 202 | dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", |
157 | 203 | error); |
158 | 204 | goto out; |
159 | 205 | } |
160 | 206 | |
161 | - if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { | |
162 | - dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", | |
163 | - rdbuf[0], rdbuf[1], rdbuf[2]); | |
164 | - goto out; | |
207 | + /* M09 does not send header or CRC */ | |
208 | + if (tsdata->version == M06) { | |
209 | + if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || | |
210 | + rdbuf[2] != datalen) { | |
211 | + dev_err_ratelimited(dev, | |
212 | + "Unexpected header: %02x%02x%02x!\n", | |
213 | + rdbuf[0], rdbuf[1], rdbuf[2]); | |
214 | + goto out; | |
215 | + } | |
216 | + | |
217 | + if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen)) | |
218 | + goto out; | |
165 | 219 | } |
166 | 220 | |
167 | - if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) | |
168 | - goto out; | |
169 | - | |
170 | 221 | for (i = 0; i < MAX_SUPPORT_POINTS; i++) { |
171 | - u8 *buf = &rdbuf[i * 4 + 5]; | |
222 | + u8 *buf = &rdbuf[i * tplen + offset]; | |
172 | 223 | bool down; |
173 | 224 | |
174 | 225 | type = buf[0] >> 6; |
... | ... | @@ -176,8 +227,8 @@ |
176 | 227 | if (type == TOUCH_EVENT_RESERVED) |
177 | 228 | continue; |
178 | 229 | |
179 | - /* ignore TOUCH_DOWN events, might have bogus coordinates */ | |
180 | - if (type == TOUCH_EVENT_DOWN) | |
230 | + /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ | |
231 | + if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN) | |
181 | 232 | continue; |
182 | 233 | |
183 | 234 | x = ((buf[0] << 8) | buf[1]) & 0x0fff; |
184 | 235 | |
... | ... | @@ -207,12 +258,25 @@ |
207 | 258 | { |
208 | 259 | u8 wrbuf[4]; |
209 | 260 | |
210 | - wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | |
211 | - wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
212 | - wrbuf[2] = value; | |
213 | - wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | |
261 | + switch (tsdata->version) { | |
262 | + case M06: | |
263 | + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | |
264 | + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
265 | + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
266 | + wrbuf[2] = value; | |
267 | + wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; | |
268 | + return edt_ft5x06_ts_readwrite(tsdata->client, 4, | |
269 | + wrbuf, 0, NULL); | |
270 | + case M09: | |
271 | + wrbuf[0] = addr; | |
272 | + wrbuf[1] = value; | |
214 | 273 | |
215 | - return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); | |
274 | + return edt_ft5x06_ts_readwrite(tsdata->client, 3, | |
275 | + wrbuf, 0, NULL); | |
276 | + | |
277 | + default: | |
278 | + return -EINVAL; | |
279 | + } | |
216 | 280 | } |
217 | 281 | |
218 | 282 | static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, |
219 | 283 | |
220 | 284 | |
... | ... | @@ -221,19 +285,35 @@ |
221 | 285 | u8 wrbuf[2], rdbuf[2]; |
222 | 286 | int error; |
223 | 287 | |
224 | - wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | |
225 | - wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
226 | - wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; | |
288 | + switch (tsdata->version) { | |
289 | + case M06: | |
290 | + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; | |
291 | + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; | |
292 | + wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; | |
227 | 293 | |
228 | - error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf); | |
229 | - if (error) | |
294 | + error = edt_ft5x06_ts_readwrite(tsdata->client, | |
295 | + 2, wrbuf, 2, rdbuf); | |
230 | 296 | return error; |
231 | 297 | |
232 | - if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { | |
233 | - dev_err(&tsdata->client->dev, | |
234 | - "crc error: 0x%02x expected, got 0x%02x\n", | |
235 | - wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); | |
236 | - return -EIO; | |
298 | + if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { | |
299 | + dev_err(&tsdata->client->dev, | |
300 | + "crc error: 0x%02x expected, got 0x%02x\n", | |
301 | + wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], | |
302 | + rdbuf[1]); | |
303 | + return -EIO; | |
304 | + } | |
305 | + break; | |
306 | + | |
307 | + case M09: | |
308 | + wrbuf[0] = addr; | |
309 | + error = edt_ft5x06_ts_readwrite(tsdata->client, 1, | |
310 | + wrbuf, 1, rdbuf); | |
311 | + if (error) | |
312 | + return error; | |
313 | + break; | |
314 | + | |
315 | + default: | |
316 | + return -EINVAL; | |
237 | 317 | } |
238 | 318 | |
239 | 319 | return rdbuf[0]; |
240 | 320 | |
241 | 321 | |
242 | 322 | |
... | ... | @@ -244,19 +324,21 @@ |
244 | 324 | size_t field_offset; |
245 | 325 | u8 limit_low; |
246 | 326 | u8 limit_high; |
247 | - u8 addr; | |
327 | + u8 addr_m06; | |
328 | + u8 addr_m09; | |
248 | 329 | }; |
249 | 330 | |
250 | -#define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \ | |
331 | +#define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, \ | |
332 | + _limit_low, _limit_high) \ | |
251 | 333 | struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ |
252 | 334 | .dattr = __ATTR(_field, _mode, \ |
253 | 335 | edt_ft5x06_setting_show, \ |
254 | 336 | edt_ft5x06_setting_store), \ |
255 | - .field_offset = \ | |
256 | - offsetof(struct edt_ft5x06_ts_data, _field), \ | |
337 | + .field_offset = offsetof(struct edt_ft5x06_ts_data, _field), \ | |
338 | + .addr_m06 = _addr_m06, \ | |
339 | + .addr_m09 = _addr_m09, \ | |
257 | 340 | .limit_low = _limit_low, \ |
258 | 341 | .limit_high = _limit_high, \ |
259 | - .addr = _addr, \ | |
260 | 342 | } |
261 | 343 | |
262 | 344 | static ssize_t edt_ft5x06_setting_show(struct device *dev, |
... | ... | @@ -271,6 +353,7 @@ |
271 | 353 | int val; |
272 | 354 | size_t count = 0; |
273 | 355 | int error = 0; |
356 | + u8 addr; | |
274 | 357 | |
275 | 358 | mutex_lock(&tsdata->mutex); |
276 | 359 | |
277 | 360 | |
... | ... | @@ -279,15 +362,33 @@ |
279 | 362 | goto out; |
280 | 363 | } |
281 | 364 | |
282 | - val = edt_ft5x06_register_read(tsdata, attr->addr); | |
283 | - if (val < 0) { | |
284 | - error = val; | |
285 | - dev_err(&tsdata->client->dev, | |
286 | - "Failed to fetch attribute %s, error %d\n", | |
287 | - dattr->attr.name, error); | |
365 | + switch (tsdata->version) { | |
366 | + case M06: | |
367 | + addr = attr->addr_m06; | |
368 | + break; | |
369 | + | |
370 | + case M09: | |
371 | + addr = attr->addr_m09; | |
372 | + break; | |
373 | + | |
374 | + default: | |
375 | + error = -ENODEV; | |
288 | 376 | goto out; |
289 | 377 | } |
290 | 378 | |
379 | + if (addr != NO_REGISTER) { | |
380 | + val = edt_ft5x06_register_read(tsdata, addr); | |
381 | + if (val < 0) { | |
382 | + error = val; | |
383 | + dev_err(&tsdata->client->dev, | |
384 | + "Failed to fetch attribute %s, error %d\n", | |
385 | + dattr->attr.name, error); | |
386 | + goto out; | |
387 | + } | |
388 | + } else { | |
389 | + val = *field; | |
390 | + } | |
391 | + | |
291 | 392 | if (val != *field) { |
292 | 393 | dev_warn(&tsdata->client->dev, |
293 | 394 | "%s: read (%d) and stored value (%d) differ\n", |
... | ... | @@ -312,6 +413,7 @@ |
312 | 413 | u8 *field = (u8 *)tsdata + attr->field_offset; |
313 | 414 | unsigned int val; |
314 | 415 | int error; |
416 | + u8 addr; | |
315 | 417 | |
316 | 418 | mutex_lock(&tsdata->mutex); |
317 | 419 | |
318 | 420 | |
... | ... | @@ -329,14 +431,29 @@ |
329 | 431 | goto out; |
330 | 432 | } |
331 | 433 | |
332 | - error = edt_ft5x06_register_write(tsdata, attr->addr, val); | |
333 | - if (error) { | |
334 | - dev_err(&tsdata->client->dev, | |
335 | - "Failed to update attribute %s, error: %d\n", | |
336 | - dattr->attr.name, error); | |
434 | + switch (tsdata->version) { | |
435 | + case M06: | |
436 | + addr = attr->addr_m06; | |
437 | + break; | |
438 | + | |
439 | + case M09: | |
440 | + addr = attr->addr_m09; | |
441 | + break; | |
442 | + | |
443 | + default: | |
444 | + error = -ENODEV; | |
337 | 445 | goto out; |
338 | 446 | } |
339 | 447 | |
448 | + if (addr != NO_REGISTER) { | |
449 | + error = edt_ft5x06_register_write(tsdata, addr, val); | |
450 | + if (error) { | |
451 | + dev_err(&tsdata->client->dev, | |
452 | + "Failed to update attribute %s, error: %d\n", | |
453 | + dattr->attr.name, error); | |
454 | + goto out; | |
455 | + } | |
456 | + } | |
340 | 457 | *field = val; |
341 | 458 | |
342 | 459 | out: |
... | ... | @@ -344,12 +461,14 @@ |
344 | 461 | return error ?: count; |
345 | 462 | } |
346 | 463 | |
347 | -static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); | |
348 | -static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); | |
349 | -static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, | |
350 | - WORK_REGISTER_THRESHOLD, 20, 80); | |
351 | -static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, | |
352 | - WORK_REGISTER_REPORT_RATE, 3, 14); | |
464 | +static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, | |
465 | + M09_REGISTER_GAIN, 0, 31); | |
466 | +static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, | |
467 | + M09_REGISTER_OFFSET, 0, 31); | |
468 | +static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, | |
469 | + M09_REGISTER_THRESHOLD, 20, 80); | |
470 | +static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, | |
471 | + NO_REGISTER, 3, 14); | |
353 | 472 | |
354 | 473 | static struct attribute *edt_ft5x06_attrs[] = { |
355 | 474 | &edt_ft5x06_attr_gain.dattr.attr, |
... | ... | @@ -384,6 +503,9 @@ |
384 | 503 | } |
385 | 504 | |
386 | 505 | /* mode register is 0x3c when in the work mode */ |
506 | + if (tsdata->version == M09) | |
507 | + goto m09_out; | |
508 | + | |
387 | 509 | error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); |
388 | 510 | if (error) { |
389 | 511 | dev_err(&client->dev, |
390 | 512 | |
... | ... | @@ -416,12 +538,18 @@ |
416 | 538 | enable_irq(client->irq); |
417 | 539 | |
418 | 540 | return error; |
541 | + | |
542 | +m09_out: | |
543 | + dev_err(&client->dev, "No factory mode support for M09\n"); | |
544 | + return -EINVAL; | |
545 | + | |
419 | 546 | } |
420 | 547 | |
421 | 548 | static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) |
422 | 549 | { |
423 | 550 | struct i2c_client *client = tsdata->client; |
424 | 551 | int retries = EDT_SWITCH_MODE_RETRIES; |
552 | + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | |
425 | 553 | int ret; |
426 | 554 | int error; |
427 | 555 | |
428 | 556 | |
429 | 557 | |
430 | 558 | |
... | ... | @@ -454,13 +582,14 @@ |
454 | 582 | tsdata->raw_buffer = NULL; |
455 | 583 | |
456 | 584 | /* restore parameters */ |
457 | - edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, | |
585 | + edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, | |
458 | 586 | tsdata->threshold); |
459 | - edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, | |
587 | + edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, | |
460 | 588 | tsdata->gain); |
461 | - edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, | |
589 | + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, | |
462 | 590 | tsdata->offset); |
463 | - edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE, | |
591 | + if (reg_addr->reg_report_rate) | |
592 | + edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, | |
464 | 593 | tsdata->report_rate); |
465 | 594 | |
466 | 595 | enable_irq(client->irq); |
467 | 596 | |
468 | 597 | |
469 | 598 | |
470 | 599 | |
471 | 600 | |
472 | 601 | |
... | ... | @@ -663,31 +792,61 @@ |
663 | 792 | } |
664 | 793 | |
665 | 794 | static int edt_ft5x06_ts_identify(struct i2c_client *client, |
666 | - char *model_name, | |
667 | - char *fw_version) | |
795 | + struct edt_ft5x06_ts_data *tsdata, | |
796 | + char *fw_version) | |
668 | 797 | { |
669 | 798 | u8 rdbuf[EDT_NAME_LEN]; |
670 | 799 | char *p; |
671 | 800 | int error; |
801 | + char *model_name = tsdata->name; | |
672 | 802 | |
803 | + /* see what we find if we assume it is a M06 * | |
804 | + * if we get less than EDT_NAME_LEN, we don't want | |
805 | + * to have garbage in there | |
806 | + */ | |
807 | + memset(rdbuf, 0, sizeof(rdbuf)); | |
673 | 808 | error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", |
674 | 809 | EDT_NAME_LEN - 1, rdbuf); |
675 | 810 | if (error) |
676 | 811 | return error; |
677 | 812 | |
678 | - /* remove last '$' end marker */ | |
679 | - rdbuf[EDT_NAME_LEN - 1] = '\0'; | |
680 | - if (rdbuf[EDT_NAME_LEN - 2] == '$') | |
681 | - rdbuf[EDT_NAME_LEN - 2] = '\0'; | |
813 | + /* if we find something consistent, stay with that assumption | |
814 | + * at least M09 won't send 3 bytes here | |
815 | + */ | |
816 | + if (!(strnicmp(rdbuf + 1, "EP0", 3))) { | |
817 | + tsdata->version = M06; | |
682 | 818 | |
683 | - /* look for Model/Version separator */ | |
684 | - p = strchr(rdbuf, '*'); | |
685 | - if (p) | |
686 | - *p++ = '\0'; | |
819 | + /* remove last '$' end marker */ | |
820 | + rdbuf[EDT_NAME_LEN - 1] = '\0'; | |
821 | + if (rdbuf[EDT_NAME_LEN - 2] == '$') | |
822 | + rdbuf[EDT_NAME_LEN - 2] = '\0'; | |
687 | 823 | |
688 | - strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); | |
689 | - strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); | |
824 | + /* look for Model/Version separator */ | |
825 | + p = strchr(rdbuf, '*'); | |
826 | + if (p) | |
827 | + *p++ = '\0'; | |
828 | + strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); | |
829 | + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); | |
830 | + } else { | |
831 | + /* since there are only two versions around (M06, M09) */ | |
832 | + tsdata->version = M09; | |
690 | 833 | |
834 | + error = edt_ft5x06_ts_readwrite(client, 1, "\xA6", | |
835 | + 2, rdbuf); | |
836 | + if (error) | |
837 | + return error; | |
838 | + | |
839 | + strlcpy(fw_version, rdbuf, 2); | |
840 | + | |
841 | + error = edt_ft5x06_ts_readwrite(client, 1, "\xA8", | |
842 | + 1, rdbuf); | |
843 | + if (error) | |
844 | + return error; | |
845 | + | |
846 | + snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", | |
847 | + rdbuf[0] >> 4, rdbuf[0] & 0x0F); | |
848 | + } | |
849 | + | |
691 | 850 | return 0; |
692 | 851 | } |
693 | 852 | |
694 | 853 | |
695 | 854 | |
696 | 855 | |
697 | 856 | |
698 | 857 | |
... | ... | @@ -705,38 +864,71 @@ |
705 | 864 | static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, |
706 | 865 | struct edt_ft5x06_ts_data *tsdata) |
707 | 866 | { |
708 | - EDT_GET_PROP(threshold, WORK_REGISTER_THRESHOLD); | |
709 | - EDT_GET_PROP(gain, WORK_REGISTER_GAIN); | |
710 | - EDT_GET_PROP(offset, WORK_REGISTER_OFFSET); | |
867 | + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | |
868 | + | |
869 | + EDT_GET_PROP(threshold, reg_addr->reg_threshold); | |
870 | + EDT_GET_PROP(gain, reg_addr->reg_gain); | |
871 | + EDT_GET_PROP(offset, reg_addr->reg_offset); | |
711 | 872 | } |
712 | 873 | |
713 | 874 | static void |
714 | 875 | edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, |
715 | 876 | const struct edt_ft5x06_platform_data *pdata) |
716 | 877 | { |
878 | + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | |
879 | + | |
717 | 880 | if (!pdata->use_parameters) |
718 | 881 | return; |
719 | 882 | |
720 | 883 | /* pick up defaults from the platform data */ |
721 | - EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); | |
722 | - EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); | |
723 | - EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); | |
724 | - EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); | |
884 | + EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold); | |
885 | + EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain); | |
886 | + EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset); | |
887 | + if (reg_addr->reg_report_rate != NO_REGISTER) | |
888 | + EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate); | |
725 | 889 | } |
726 | 890 | |
727 | 891 | static void |
728 | 892 | edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) |
729 | 893 | { |
894 | + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | |
895 | + | |
730 | 896 | tsdata->threshold = edt_ft5x06_register_read(tsdata, |
731 | - WORK_REGISTER_THRESHOLD); | |
732 | - tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); | |
733 | - tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); | |
734 | - tsdata->report_rate = edt_ft5x06_register_read(tsdata, | |
735 | - WORK_REGISTER_REPORT_RATE); | |
736 | - tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); | |
737 | - tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); | |
897 | + reg_addr->reg_threshold); | |
898 | + tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain); | |
899 | + tsdata->offset = edt_ft5x06_register_read(tsdata, reg_addr->reg_offset); | |
900 | + if (reg_addr->reg_report_rate != NO_REGISTER) | |
901 | + tsdata->report_rate = edt_ft5x06_register_read(tsdata, | |
902 | + reg_addr->reg_report_rate); | |
903 | + tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x); | |
904 | + tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y); | |
738 | 905 | } |
739 | 906 | |
907 | +static void | |
908 | +edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) | |
909 | +{ | |
910 | + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; | |
911 | + | |
912 | + switch (tsdata->version) { | |
913 | + case M06: | |
914 | + reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; | |
915 | + reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; | |
916 | + reg_addr->reg_gain = WORK_REGISTER_GAIN; | |
917 | + reg_addr->reg_offset = WORK_REGISTER_OFFSET; | |
918 | + reg_addr->reg_num_x = WORK_REGISTER_NUM_X; | |
919 | + reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; | |
920 | + break; | |
921 | + | |
922 | + case M09: | |
923 | + reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; | |
924 | + reg_addr->reg_gain = M09_REGISTER_GAIN; | |
925 | + reg_addr->reg_offset = M09_REGISTER_OFFSET; | |
926 | + reg_addr->reg_num_x = M09_REGISTER_NUM_X; | |
927 | + reg_addr->reg_num_y = M09_REGISTER_NUM_Y; | |
928 | + break; | |
929 | + } | |
930 | +} | |
931 | + | |
740 | 932 | #ifdef CONFIG_OF |
741 | 933 | static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, |
742 | 934 | struct edt_ft5x06_ts_data *tsdata) |
743 | 935 | |
... | ... | @@ -818,11 +1010,13 @@ |
818 | 1010 | tsdata->input = input; |
819 | 1011 | tsdata->factory_mode = false; |
820 | 1012 | |
821 | - error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version); | |
1013 | + error = edt_ft5x06_ts_identify(client, tsdata, fw_version); | |
822 | 1014 | if (error) { |
823 | 1015 | dev_err(&client->dev, "touchscreen probe failed\n"); |
824 | 1016 | return error; |
825 | 1017 | } |
1018 | + | |
1019 | + edt_ft5x06_ts_set_regs(tsdata); | |
826 | 1020 | |
827 | 1021 | if (!pdata) |
828 | 1022 | edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata); |