aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/edt-ft5x06.c
diff options
context:
space:
mode:
authorLothar Waßmann <LW@KARO-electronics.de>2014-03-28 12:31:14 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-03-28 12:33:07 -0400
commitfd335ab04b3f1b3309dfbfea71a1a79a7bacc4ad (patch)
tree7ee9107cdec1eefb5587a3c67429c762e5c08d5a /drivers/input/touchscreen/edt-ft5x06.c
parentee3e946e31e6df0f9845f9b3d527252003603530 (diff)
Input: edt-ft5x06 - add support for M09 firmware version
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>
Diffstat (limited to 'drivers/input/touchscreen/edt-ft5x06.c')
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c358
1 files changed, 276 insertions, 82 deletions
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index dd94b9eea6e7..75b666bd2654 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de> 2 * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
3 * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
3 * Lothar Waßmann <LW@KARO-electronics.de> (DT support) 4 * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
4 * 5 *
5 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
@@ -47,6 +48,14 @@
47#define WORK_REGISTER_NUM_X 0x33 48#define WORK_REGISTER_NUM_X 0x33
48#define WORK_REGISTER_NUM_Y 0x34 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#define WORK_REGISTER_OPMODE 0x3c 59#define WORK_REGISTER_OPMODE 0x3c
51#define FACTORY_REGISTER_OPMODE 0x01 60#define FACTORY_REGISTER_OPMODE 0x01
52 61
@@ -61,6 +70,20 @@
61#define EDT_RAW_DATA_RETRIES 100 70#define EDT_RAW_DATA_RETRIES 100
62#define EDT_RAW_DATA_DELAY 1 /* msec */ 71#define EDT_RAW_DATA_DELAY 1 /* msec */
63 72
73enum edt_ver {
74 M06,
75 M09,
76};
77
78struct 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
64struct edt_ft5x06_ts_data { 87struct edt_ft5x06_ts_data {
65 struct i2c_client *client; 88 struct i2c_client *client;
66 struct input_dev *input; 89 struct input_dev *input;
@@ -85,6 +108,9 @@ struct edt_ft5x06_ts_data {
85 int report_rate; 108 int report_rate;
86 109
87 char name[EDT_NAME_LEN]; 110 char name[EDT_NAME_LEN];
111
112 struct edt_reg_addr reg_addr;
113 enum edt_ver version;
88}; 114};
89 115
90static int edt_ft5x06_ts_readwrite(struct i2c_client *client, 116static int edt_ft5x06_ts_readwrite(struct i2c_client *client,
@@ -142,33 +168,58 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
142{ 168{
143 struct edt_ft5x06_ts_data *tsdata = dev_id; 169 struct edt_ft5x06_ts_data *tsdata = dev_id;
144 struct device *dev = &tsdata->client->dev; 170 struct device *dev = &tsdata->client->dev;
145 u8 cmd = 0xf9; 171 u8 cmd;
146 u8 rdbuf[26]; 172 u8 rdbuf[29];
147 int i, type, x, y, id; 173 int i, type, x, y, id;
174 int offset, tplen, datalen;
148 int error; 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 memset(rdbuf, 0, sizeof(rdbuf)); 196 memset(rdbuf, 0, sizeof(rdbuf));
151 197
152 error = edt_ft5x06_ts_readwrite(tsdata->client, 198 error = edt_ft5x06_ts_readwrite(tsdata->client,
153 sizeof(cmd), &cmd, 199 sizeof(cmd), &cmd,
154 sizeof(rdbuf), rdbuf); 200 datalen, rdbuf);
155 if (error) { 201 if (error) {
156 dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", 202 dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
157 error); 203 error);
158 goto out; 204 goto out;
159 } 205 }
160 206
161 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) { 207 /* M09 does not send header or CRC */
162 dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n", 208 if (tsdata->version == M06) {
163 rdbuf[0], rdbuf[1], rdbuf[2]); 209 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
164 goto out; 210 rdbuf[2] != datalen) {
165 } 211 dev_err_ratelimited(dev,
212 "Unexpected header: %02x%02x%02x!\n",
213 rdbuf[0], rdbuf[1], rdbuf[2]);
214 goto out;
215 }
166 216
167 if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26)) 217 if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen))
168 goto out; 218 goto out;
219 }
169 220
170 for (i = 0; i < MAX_SUPPORT_POINTS; i++) { 221 for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
171 u8 *buf = &rdbuf[i * 4 + 5]; 222 u8 *buf = &rdbuf[i * tplen + offset];
172 bool down; 223 bool down;
173 224
174 type = buf[0] >> 6; 225 type = buf[0] >> 6;
@@ -176,8 +227,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
176 if (type == TOUCH_EVENT_RESERVED) 227 if (type == TOUCH_EVENT_RESERVED)
177 continue; 228 continue;
178 229
179 /* ignore TOUCH_DOWN events, might have bogus coordinates */ 230 /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */
180 if (type == TOUCH_EVENT_DOWN) 231 if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN)
181 continue; 232 continue;
182 233
183 x = ((buf[0] << 8) | buf[1]) & 0x0fff; 234 x = ((buf[0] << 8) | buf[1]) & 0x0fff;
@@ -207,12 +258,25 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
207{ 258{
208 u8 wrbuf[4]; 259 u8 wrbuf[4];
209 260
210 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 261 switch (tsdata->version) {
211 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 262 case M06:
212 wrbuf[2] = value; 263 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
213 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; 264 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
214 265 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
215 return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); 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;
273
274 return edt_ft5x06_ts_readwrite(tsdata->client, 3,
275 wrbuf, 0, NULL);
276
277 default:
278 return -EINVAL;
279 }
216} 280}
217 281
218static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, 282static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
@@ -221,19 +285,35 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
221 u8 wrbuf[2], rdbuf[2]; 285 u8 wrbuf[2], rdbuf[2];
222 int error; 286 int error;
223 287
224 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 288 switch (tsdata->version) {
225 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 289 case M06:
226 wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; 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); 294 error = edt_ft5x06_ts_readwrite(tsdata->client,
229 if (error) 295 2, wrbuf, 2, rdbuf);
230 return error; 296 return error;
231 297
232 if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) { 298 if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) {
233 dev_err(&tsdata->client->dev, 299 dev_err(&tsdata->client->dev,
234 "crc error: 0x%02x expected, got 0x%02x\n", 300 "crc error: 0x%02x expected, got 0x%02x\n",
235 wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]); 301 wrbuf[0] ^ wrbuf[1] ^ rdbuf[0],
236 return -EIO; 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 return rdbuf[0]; 319 return rdbuf[0];
@@ -244,19 +324,21 @@ struct edt_ft5x06_attribute {
244 size_t field_offset; 324 size_t field_offset;
245 u8 limit_low; 325 u8 limit_low;
246 u8 limit_high; 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 struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \ 333 struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \
252 .dattr = __ATTR(_field, _mode, \ 334 .dattr = __ATTR(_field, _mode, \
253 edt_ft5x06_setting_show, \ 335 edt_ft5x06_setting_show, \
254 edt_ft5x06_setting_store), \ 336 edt_ft5x06_setting_store), \
255 .field_offset = \ 337 .field_offset = offsetof(struct edt_ft5x06_ts_data, _field), \
256 offsetof(struct edt_ft5x06_ts_data, _field), \ 338 .addr_m06 = _addr_m06, \
339 .addr_m09 = _addr_m09, \
257 .limit_low = _limit_low, \ 340 .limit_low = _limit_low, \
258 .limit_high = _limit_high, \ 341 .limit_high = _limit_high, \
259 .addr = _addr, \
260 } 342 }
261 343
262static ssize_t edt_ft5x06_setting_show(struct device *dev, 344static ssize_t edt_ft5x06_setting_show(struct device *dev,
@@ -271,6 +353,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
271 int val; 353 int val;
272 size_t count = 0; 354 size_t count = 0;
273 int error = 0; 355 int error = 0;
356 u8 addr;
274 357
275 mutex_lock(&tsdata->mutex); 358 mutex_lock(&tsdata->mutex);
276 359
@@ -279,15 +362,33 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
279 goto out; 362 goto out;
280 } 363 }
281 364
282 val = edt_ft5x06_register_read(tsdata, attr->addr); 365 switch (tsdata->version) {
283 if (val < 0) { 366 case M06:
284 error = val; 367 addr = attr->addr_m06;
285 dev_err(&tsdata->client->dev, 368 break;
286 "Failed to fetch attribute %s, error %d\n", 369
287 dattr->attr.name, error); 370 case M09:
371 addr = attr->addr_m09;
372 break;
373
374 default:
375 error = -ENODEV;
288 goto out; 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 if (val != *field) { 392 if (val != *field) {
292 dev_warn(&tsdata->client->dev, 393 dev_warn(&tsdata->client->dev,
293 "%s: read (%d) and stored value (%d) differ\n", 394 "%s: read (%d) and stored value (%d) differ\n",
@@ -312,6 +413,7 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
312 u8 *field = (u8 *)tsdata + attr->field_offset; 413 u8 *field = (u8 *)tsdata + attr->field_offset;
313 unsigned int val; 414 unsigned int val;
314 int error; 415 int error;
416 u8 addr;
315 417
316 mutex_lock(&tsdata->mutex); 418 mutex_lock(&tsdata->mutex);
317 419
@@ -329,14 +431,29 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
329 goto out; 431 goto out;
330 } 432 }
331 433
332 error = edt_ft5x06_register_write(tsdata, attr->addr, val); 434 switch (tsdata->version) {
333 if (error) { 435 case M06:
334 dev_err(&tsdata->client->dev, 436 addr = attr->addr_m06;
335 "Failed to update attribute %s, error: %d\n", 437 break;
336 dattr->attr.name, error); 438
439 case M09:
440 addr = attr->addr_m09;
441 break;
442
443 default:
444 error = -ENODEV;
337 goto out; 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 *field = val; 457 *field = val;
341 458
342out: 459out:
@@ -344,12 +461,14 @@ out:
344 return error ?: count; 461 return error ?: count;
345} 462}
346 463
347static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31); 464static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
348static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31); 465 M09_REGISTER_GAIN, 0, 31);
349static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, 466static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
350 WORK_REGISTER_THRESHOLD, 20, 80); 467 M09_REGISTER_OFFSET, 0, 31);
351static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, 468static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
352 WORK_REGISTER_REPORT_RATE, 3, 14); 469 M09_REGISTER_THRESHOLD, 20, 80);
470static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
471 NO_REGISTER, 3, 14);
353 472
354static struct attribute *edt_ft5x06_attrs[] = { 473static struct attribute *edt_ft5x06_attrs[] = {
355 &edt_ft5x06_attr_gain.dattr.attr, 474 &edt_ft5x06_attr_gain.dattr.attr,
@@ -384,6 +503,9 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
384 } 503 }
385 504
386 /* mode register is 0x3c when in the work mode */ 505 /* mode register is 0x3c when in the work mode */
506 if (tsdata->version == M09)
507 goto m09_out;
508
387 error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); 509 error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
388 if (error) { 510 if (error) {
389 dev_err(&client->dev, 511 dev_err(&client->dev,
@@ -416,12 +538,18 @@ err_out:
416 enable_irq(client->irq); 538 enable_irq(client->irq);
417 539
418 return error; 540 return error;
541
542m09_out:
543 dev_err(&client->dev, "No factory mode support for M09\n");
544 return -EINVAL;
545
419} 546}
420 547
421static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) 548static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
422{ 549{
423 struct i2c_client *client = tsdata->client; 550 struct i2c_client *client = tsdata->client;
424 int retries = EDT_SWITCH_MODE_RETRIES; 551 int retries = EDT_SWITCH_MODE_RETRIES;
552 struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
425 int ret; 553 int ret;
426 int error; 554 int error;
427 555
@@ -454,13 +582,14 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
454 tsdata->raw_buffer = NULL; 582 tsdata->raw_buffer = NULL;
455 583
456 /* restore parameters */ 584 /* restore parameters */
457 edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD, 585 edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold,
458 tsdata->threshold); 586 tsdata->threshold);
459 edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN, 587 edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
460 tsdata->gain); 588 tsdata->gain);
461 edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET, 589 edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
462 tsdata->offset); 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 tsdata->report_rate); 593 tsdata->report_rate);
465 594
466 enable_irq(client->irq); 595 enable_irq(client->irq);
@@ -663,30 +792,60 @@ static int edt_ft5x06_ts_reset(struct i2c_client *client,
663} 792}
664 793
665static int edt_ft5x06_ts_identify(struct i2c_client *client, 794static int edt_ft5x06_ts_identify(struct i2c_client *client,
666 char *model_name, 795 struct edt_ft5x06_ts_data *tsdata,
667 char *fw_version) 796 char *fw_version)
668{ 797{
669 u8 rdbuf[EDT_NAME_LEN]; 798 u8 rdbuf[EDT_NAME_LEN];
670 char *p; 799 char *p;
671 int error; 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 error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", 808 error = edt_ft5x06_ts_readwrite(client, 1, "\xbb",
674 EDT_NAME_LEN - 1, rdbuf); 809 EDT_NAME_LEN - 1, rdbuf);
675 if (error) 810 if (error)
676 return error; 811 return error;
677 812
678 /* remove last '$' end marker */ 813 /* if we find something consistent, stay with that assumption
679 rdbuf[EDT_NAME_LEN - 1] = '\0'; 814 * at least M09 won't send 3 bytes here
680 if (rdbuf[EDT_NAME_LEN - 2] == '$') 815 */
681 rdbuf[EDT_NAME_LEN - 2] = '\0'; 816 if (!(strnicmp(rdbuf + 1, "EP0", 3))) {
817 tsdata->version = M06;
818
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';
823
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;
833
834 error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
835 2, rdbuf);
836 if (error)
837 return error;
682 838
683 /* look for Model/Version separator */ 839 strlcpy(fw_version, rdbuf, 2);
684 p = strchr(rdbuf, '*');
685 if (p)
686 *p++ = '\0';
687 840
688 strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); 841 error = edt_ft5x06_ts_readwrite(client, 1, "\xA8",
689 strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); 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 }
690 849
691 return 0; 850 return 0;
692} 851}
@@ -705,36 +864,69 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
705static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, 864static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np,
706 struct edt_ft5x06_ts_data *tsdata) 865 struct edt_ft5x06_ts_data *tsdata)
707{ 866{
708 EDT_GET_PROP(threshold, WORK_REGISTER_THRESHOLD); 867 struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
709 EDT_GET_PROP(gain, WORK_REGISTER_GAIN); 868
710 EDT_GET_PROP(offset, WORK_REGISTER_OFFSET); 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
713static void 874static void
714edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, 875edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
715 const struct edt_ft5x06_platform_data *pdata) 876 const struct edt_ft5x06_platform_data *pdata)
716{ 877{
878 struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
879
717 if (!pdata->use_parameters) 880 if (!pdata->use_parameters)
718 return; 881 return;
719 882
720 /* pick up defaults from the platform data */ 883 /* pick up defaults from the platform data */
721 EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD); 884 EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold);
722 EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN); 885 EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain);
723 EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET); 886 EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset);
724 EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); 887 if (reg_addr->reg_report_rate != NO_REGISTER)
888 EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate);
725} 889}
726 890
727static void 891static void
728edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) 892edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
729{ 893{
894 struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
895
730 tsdata->threshold = edt_ft5x06_register_read(tsdata, 896 tsdata->threshold = edt_ft5x06_register_read(tsdata,
731 WORK_REGISTER_THRESHOLD); 897 reg_addr->reg_threshold);
732 tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN); 898 tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain);
733 tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET); 899 tsdata->offset = edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
734 tsdata->report_rate = edt_ft5x06_register_read(tsdata, 900 if (reg_addr->reg_report_rate != NO_REGISTER)
735 WORK_REGISTER_REPORT_RATE); 901 tsdata->report_rate = edt_ft5x06_register_read(tsdata,
736 tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X); 902 reg_addr->reg_report_rate);
737 tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); 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);
905}
906
907static void
908edt_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 }
738} 930}
739 931
740#ifdef CONFIG_OF 932#ifdef CONFIG_OF
@@ -818,12 +1010,14 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
818 tsdata->input = input; 1010 tsdata->input = input;
819 tsdata->factory_mode = false; 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 if (error) { 1014 if (error) {
823 dev_err(&client->dev, "touchscreen probe failed\n"); 1015 dev_err(&client->dev, "touchscreen probe failed\n");
824 return error; 1016 return error;
825 } 1017 }
826 1018
1019 edt_ft5x06_ts_set_regs(tsdata);
1020
827 if (!pdata) 1021 if (!pdata)
828 edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata); 1022 edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata);
829 else 1023 else