aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Budig <simon.budig@kernelconcepts.de>2017-10-09 23:58:11 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-10-19 20:17:46 -0400
commit169110c3645621497ca0b1d0d7bc80dcea8ff9d4 (patch)
tree54f0b52dbb369d13792f50d0352668774ccf0f69
parentadb77b3e5118d2760621d8cc740524b816f9006b (diff)
Input: edt-ft5x06 - make distinction between m06/m09/generic more clear
Since the driver also is useful for some non-EDT touchscreens based on the focaltec chips introduce the concept of a "generic" focaltec based touch. Use a better heuristics for model detection and be more specific in the source. Signed-off-by: Simon Budig <simon.budig@kernelconcepts.de> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c122
1 files changed, 93 insertions, 29 deletions
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index f879d14f7ffc..56bfd0c14c91 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -70,8 +70,9 @@
70#define EDT_RAW_DATA_DELAY 1000 /* usec */ 70#define EDT_RAW_DATA_DELAY 1000 /* usec */
71 71
72enum edt_ver { 72enum edt_ver {
73 M06, 73 EDT_M06,
74 M09, 74 EDT_M09,
75 GENERIC_FT,
75}; 76};
76 77
77struct edt_reg_addr { 78struct edt_reg_addr {
@@ -179,14 +180,15 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
179 int error; 180 int error;
180 181
181 switch (tsdata->version) { 182 switch (tsdata->version) {
182 case M06: 183 case EDT_M06:
183 cmd = 0xf9; /* tell the controller to send touch data */ 184 cmd = 0xf9; /* tell the controller to send touch data */
184 offset = 5; /* where the actual touch data starts */ 185 offset = 5; /* where the actual touch data starts */
185 tplen = 4; /* data comes in so called frames */ 186 tplen = 4; /* data comes in so called frames */
186 crclen = 1; /* length of the crc data */ 187 crclen = 1; /* length of the crc data */
187 break; 188 break;
188 189
189 case M09: 190 case EDT_M09:
191 case GENERIC_FT:
190 cmd = 0x0; 192 cmd = 0x0;
191 offset = 3; 193 offset = 3;
192 tplen = 6; 194 tplen = 6;
@@ -210,7 +212,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
210 } 212 }
211 213
212 /* M09 does not send header or CRC */ 214 /* M09 does not send header or CRC */
213 if (tsdata->version == M06) { 215 if (tsdata->version == EDT_M06) {
214 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || 216 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
215 rdbuf[2] != datalen) { 217 rdbuf[2] != datalen) {
216 dev_err_ratelimited(dev, 218 dev_err_ratelimited(dev,
@@ -233,7 +235,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
233 continue; 235 continue;
234 236
235 /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ 237 /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */
236 if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN) 238 if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
237 continue; 239 continue;
238 240
239 x = ((buf[0] << 8) | buf[1]) & 0x0fff; 241 x = ((buf[0] << 8) | buf[1]) & 0x0fff;
@@ -264,14 +266,15 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
264 u8 wrbuf[4]; 266 u8 wrbuf[4];
265 267
266 switch (tsdata->version) { 268 switch (tsdata->version) {
267 case M06: 269 case EDT_M06:
268 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 270 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
269 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 271 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
270 wrbuf[2] = value; 272 wrbuf[2] = value;
271 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; 273 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
272 return edt_ft5x06_ts_readwrite(tsdata->client, 4, 274 return edt_ft5x06_ts_readwrite(tsdata->client, 4,
273 wrbuf, 0, NULL); 275 wrbuf, 0, NULL);
274 case M09: 276 case EDT_M09:
277 case GENERIC_FT:
275 wrbuf[0] = addr; 278 wrbuf[0] = addr;
276 wrbuf[1] = value; 279 wrbuf[1] = value;
277 280
@@ -290,7 +293,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
290 int error; 293 int error;
291 294
292 switch (tsdata->version) { 295 switch (tsdata->version) {
293 case M06: 296 case EDT_M06:
294 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; 297 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
295 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; 298 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
296 wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; 299 wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
@@ -309,7 +312,8 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
309 } 312 }
310 break; 313 break;
311 314
312 case M09: 315 case EDT_M09:
316 case GENERIC_FT:
313 wrbuf[0] = addr; 317 wrbuf[0] = addr;
314 error = edt_ft5x06_ts_readwrite(tsdata->client, 1, 318 error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
315 wrbuf, 1, rdbuf); 319 wrbuf, 1, rdbuf);
@@ -368,11 +372,12 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
368 } 372 }
369 373
370 switch (tsdata->version) { 374 switch (tsdata->version) {
371 case M06: 375 case EDT_M06:
372 addr = attr->addr_m06; 376 addr = attr->addr_m06;
373 break; 377 break;
374 378
375 case M09: 379 case EDT_M09:
380 case GENERIC_FT:
376 addr = attr->addr_m09; 381 addr = attr->addr_m09;
377 break; 382 break;
378 383
@@ -437,11 +442,12 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
437 } 442 }
438 443
439 switch (tsdata->version) { 444 switch (tsdata->version) {
440 case M06: 445 case EDT_M06:
441 addr = attr->addr_m06; 446 addr = attr->addr_m06;
442 break; 447 break;
443 448
444 case M09: 449 case EDT_M09:
450 case GENERIC_FT:
445 addr = attr->addr_m09; 451 addr = attr->addr_m09;
446 break; 452 break;
447 453
@@ -508,7 +514,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
508 } 514 }
509 515
510 /* mode register is 0x3c when in the work mode */ 516 /* mode register is 0x3c when in the work mode */
511 if (tsdata->version == M09) 517 if (tsdata->version != EDT_M06)
512 goto m09_out; 518 goto m09_out;
513 519
514 error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); 520 error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
@@ -545,7 +551,7 @@ err_out:
545 return error; 551 return error;
546 552
547m09_out: 553m09_out:
548 dev_err(&client->dev, "No factory mode support for M09\n"); 554 dev_err(&client->dev, "No factory mode support for M09/GENERIC_FT\n");
549 return -EINVAL; 555 return -EINVAL;
550 556
551} 557}
@@ -779,7 +785,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
779 * at least M09 won't send 3 bytes here 785 * at least M09 won't send 3 bytes here
780 */ 786 */
781 if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { 787 if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
782 tsdata->version = M06; 788 tsdata->version = EDT_M06;
783 789
784 /* remove last '$' end marker */ 790 /* remove last '$' end marker */
785 rdbuf[EDT_NAME_LEN - 1] = '\0'; 791 rdbuf[EDT_NAME_LEN - 1] = '\0';
@@ -793,8 +799,16 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
793 strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); 799 strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
794 strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); 800 strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
795 } else { 801 } else {
796 /* since there are only two versions around (M06, M09) */ 802 /* If it is not an EDT M06 touchscreen, then the model
797 tsdata->version = M09; 803 * detection is a bit hairy. The different ft5x06
804 * firmares around don't reliably implement the
805 * identification registers. Well, we'll take a shot.
806 *
807 * The main difference between generic focaltec based
808 * touches and EDT M09 is that we know how to retrieve
809 * the max coordinates for the latter.
810 */
811 tsdata->version = GENERIC_FT;
798 812
799 error = edt_ft5x06_ts_readwrite(client, 1, "\xA6", 813 error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
800 2, rdbuf); 814 2, rdbuf);
@@ -808,8 +822,34 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
808 if (error) 822 if (error)
809 return error; 823 return error;
810 824
811 snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", 825 /* This "model identification" is not exact. Unfortunately
812 rdbuf[0] >> 4, rdbuf[0] & 0x0F); 826 * not all firmwares for the ft5x06 put useful values in
827 * the identification registers.
828 */
829 switch (rdbuf[0]) {
830 case 0x35: /* EDT EP0350M09 */
831 case 0x43: /* EDT EP0430M09 */
832 case 0x50: /* EDT EP0500M09 */
833 case 0x57: /* EDT EP0570M09 */
834 case 0x70: /* EDT EP0700M09 */
835 tsdata->version = EDT_M09;
836 snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
837 rdbuf[0] >> 4, rdbuf[0] & 0x0F);
838 break;
839 case 0xa1: /* EDT EP1010ML00 */
840 tsdata->version = EDT_M09;
841 snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00",
842 rdbuf[0] >> 4, rdbuf[0] & 0x0F);
843 break;
844 case 0x5a: /* Solomon Goldentek Display */
845 snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
846 break;
847 default:
848 snprintf(model_name, EDT_NAME_LEN,
849 "generic ft5x06 (%02x)",
850 rdbuf[0]);
851 break;
852 }
813 } 853 }
814 854
815 return 0; 855 return 0;
@@ -853,8 +893,16 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
853 if (reg_addr->reg_report_rate != NO_REGISTER) 893 if (reg_addr->reg_report_rate != NO_REGISTER)
854 tsdata->report_rate = edt_ft5x06_register_read(tsdata, 894 tsdata->report_rate = edt_ft5x06_register_read(tsdata,
855 reg_addr->reg_report_rate); 895 reg_addr->reg_report_rate);
856 tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x); 896 if (tsdata->version == EDT_M06 ||
857 tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y); 897 tsdata->version == EDT_M09) {
898 tsdata->num_x = edt_ft5x06_register_read(tsdata,
899 reg_addr->reg_num_x);
900 tsdata->num_y = edt_ft5x06_register_read(tsdata,
901 reg_addr->reg_num_y);
902 } else {
903 tsdata->num_x = -1;
904 tsdata->num_y = -1;
905 }
858} 906}
859 907
860static void 908static void
@@ -863,7 +911,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
863 struct edt_reg_addr *reg_addr = &tsdata->reg_addr; 911 struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
864 912
865 switch (tsdata->version) { 913 switch (tsdata->version) {
866 case M06: 914 case EDT_M06:
867 reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; 915 reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD;
868 reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; 916 reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE;
869 reg_addr->reg_gain = WORK_REGISTER_GAIN; 917 reg_addr->reg_gain = WORK_REGISTER_GAIN;
@@ -872,7 +920,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
872 reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; 920 reg_addr->reg_num_y = WORK_REGISTER_NUM_Y;
873 break; 921 break;
874 922
875 case M09: 923 case EDT_M09:
876 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; 924 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
877 reg_addr->reg_report_rate = NO_REGISTER; 925 reg_addr->reg_report_rate = NO_REGISTER;
878 reg_addr->reg_gain = M09_REGISTER_GAIN; 926 reg_addr->reg_gain = M09_REGISTER_GAIN;
@@ -880,6 +928,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
880 reg_addr->reg_num_x = M09_REGISTER_NUM_X; 928 reg_addr->reg_num_x = M09_REGISTER_NUM_X;
881 reg_addr->reg_num_y = M09_REGISTER_NUM_Y; 929 reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
882 break; 930 break;
931
932 case GENERIC_FT:
933 /* this is a guesswork */
934 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
935 reg_addr->reg_gain = M09_REGISTER_GAIN;
936 reg_addr->reg_offset = M09_REGISTER_OFFSET;
937 break;
883 } 938 }
884} 939}
885 940
@@ -969,10 +1024,19 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
969 input->id.bustype = BUS_I2C; 1024 input->id.bustype = BUS_I2C;
970 input->dev.parent = &client->dev; 1025 input->dev.parent = &client->dev;
971 1026
972 input_set_abs_params(input, ABS_MT_POSITION_X, 1027 if (tsdata->version == EDT_M06 ||
973 0, tsdata->num_x * 64 - 1, 0, 0); 1028 tsdata->version == EDT_M09) {
974 input_set_abs_params(input, ABS_MT_POSITION_Y, 1029 input_set_abs_params(input, ABS_MT_POSITION_X,
975 0, tsdata->num_y * 64 - 1, 0, 0); 1030 0, tsdata->num_x * 64 - 1, 0, 0);
1031 input_set_abs_params(input, ABS_MT_POSITION_Y,
1032 0, tsdata->num_y * 64 - 1, 0, 0);
1033 } else {
1034 /* Unknown maximum values. Specify via devicetree */
1035 input_set_abs_params(input, ABS_MT_POSITION_X,
1036 0, 65535, 0, 0);
1037 input_set_abs_params(input, ABS_MT_POSITION_Y,
1038 0, 65535, 0, 0);
1039 }
976 1040
977 touchscreen_parse_properties(input, true, &tsdata->prop); 1041 touchscreen_parse_properties(input, true, &tsdata->prop);
978 1042