]> git.kernelconcepts.de Git - meta-kc-bsp.git/blob - recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-make-distinction-between.patch
2cc16b8b87bfffc7a528adbac1663356315288c3
[meta-kc-bsp.git] / recipes-kernel / linux / linux-karo-4.9.11 / edt-ft5x06-make-distinction-between.patch
1 From 169110c3645621497ca0b1d0d7bc80dcea8ff9d4 Mon Sep 17 00:00:00 2001
2 From: Simon Budig <simon.budig@kernelconcepts.de>
3 Date: Mon, 9 Oct 2017 20:58:11 -0700
4 Subject: [PATCH] Input: edt-ft5x06 - make distinction between m06/m09/generic
5  more clear
6
7 Since the driver also is useful for some non-EDT touchscreens based on
8 the focaltec chips introduce the concept of a "generic" focaltec based
9 touch.
10
11 Use a better heuristics for model detection and be more specific in the
12 source.
13
14 Signed-off-by: Simon Budig <simon.budig@kernelconcepts.de>
15 Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
16 ---
17  drivers/input/touchscreen/edt-ft5x06.c | 122 +++++++++++++++++++++++++--------
18  1 file changed, 93 insertions(+), 29 deletions(-)
19
20 diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
21 index f879d14f7ffcc..56bfd0c14c91a 100644
22 --- a/drivers/input/touchscreen/edt-ft5x06.c
23 +++ b/drivers/input/touchscreen/edt-ft5x06.c
24 @@ -70,8 +70,9 @@
25  #define EDT_RAW_DATA_DELAY             1000 /* usec */
26  
27  enum edt_ver {
28 -       M06,
29 -       M09,
30 +       EDT_M06,
31 +       EDT_M09,
32 +       GENERIC_FT,
33  };
34  
35  struct edt_reg_addr {
36 @@ -179,14 +180,15 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
37         int error;
38  
39         switch (tsdata->version) {
40 -       case M06:
41 +       case EDT_M06:
42                 cmd = 0xf9; /* tell the controller to send touch data */
43                 offset = 5; /* where the actual touch data starts */
44                 tplen = 4;  /* data comes in so called frames */
45                 crclen = 1; /* length of the crc data */
46                 break;
47  
48 -       case M09:
49 +       case EDT_M09:
50 +       case GENERIC_FT:
51                 cmd = 0x0;
52                 offset = 3;
53                 tplen = 6;
54 @@ -210,7 +212,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
55         }
56  
57         /* M09 does not send header or CRC */
58 -       if (tsdata->version == M06) {
59 +       if (tsdata->version == EDT_M06) {
60                 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
61                         rdbuf[2] != datalen) {
62                         dev_err_ratelimited(dev,
63 @@ -233,7 +235,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
64                         continue;
65  
66                 /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */
67 -               if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN)
68 +               if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
69                         continue;
70  
71                 x = ((buf[0] << 8) | buf[1]) & 0x0fff;
72 @@ -264,14 +266,15 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
73         u8 wrbuf[4];
74  
75         switch (tsdata->version) {
76 -       case M06:
77 +       case EDT_M06:
78                 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
79                 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
80                 wrbuf[2] = value;
81                 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
82                 return edt_ft5x06_ts_readwrite(tsdata->client, 4,
83                                         wrbuf, 0, NULL);
84 -       case M09:
85 +       case EDT_M09:
86 +       case GENERIC_FT:
87                 wrbuf[0] = addr;
88                 wrbuf[1] = value;
89  
90 @@ -290,7 +293,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
91         int error;
92  
93         switch (tsdata->version) {
94 -       case M06:
95 +       case EDT_M06:
96                 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
97                 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
98                 wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
99 @@ -309,7 +312,8 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
100                 }
101                 break;
102  
103 -       case M09:
104 +       case EDT_M09:
105 +       case GENERIC_FT:
106                 wrbuf[0] = addr;
107                 error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
108                                                 wrbuf, 1, rdbuf);
109 @@ -368,11 +372,12 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev,
110         }
111  
112         switch (tsdata->version) {
113 -       case M06:
114 +       case EDT_M06:
115                 addr = attr->addr_m06;
116                 break;
117  
118 -       case M09:
119 +       case EDT_M09:
120 +       case GENERIC_FT:
121                 addr = attr->addr_m09;
122                 break;
123  
124 @@ -437,11 +442,12 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev,
125         }
126  
127         switch (tsdata->version) {
128 -       case M06:
129 +       case EDT_M06:
130                 addr = attr->addr_m06;
131                 break;
132  
133 -       case M09:
134 +       case EDT_M09:
135 +       case GENERIC_FT:
136                 addr = attr->addr_m09;
137                 break;
138  
139 @@ -508,7 +514,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
140         }
141  
142         /* mode register is 0x3c when in the work mode */
143 -       if (tsdata->version == M09)
144 +       if (tsdata->version != EDT_M06)
145                 goto m09_out;
146  
147         error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
148 @@ -545,7 +551,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
149         return error;
150  
151  m09_out:
152 -       dev_err(&client->dev, "No factory mode support for M09\n");
153 +       dev_err(&client->dev, "No factory mode support for M09/GENERIC_FT\n");
154         return -EINVAL;
155  
156  }
157 @@ -779,7 +785,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
158          * at least M09 won't send 3 bytes here
159          */
160         if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
161 -               tsdata->version = M06;
162 +               tsdata->version = EDT_M06;
163  
164                 /* remove last '$' end marker */
165                 rdbuf[EDT_NAME_LEN - 1] = '\0';
166 @@ -793,8 +799,16 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
167                 strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
168                 strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
169         } else {
170 -               /* since there are only two versions around (M06, M09) */
171 -               tsdata->version = M09;
172 +               /* If it is not an EDT M06 touchscreen, then the model
173 +                * detection is a bit hairy. The different ft5x06
174 +                * firmares around don't reliably implement the
175 +                * identification registers. Well, we'll take a shot.
176 +                *
177 +                * The main difference between generic focaltec based
178 +                * touches and EDT M09 is that we know how to retrieve
179 +                * the max coordinates for the latter.
180 +                */
181 +               tsdata->version = GENERIC_FT;
182  
183                 error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
184                                                 2, rdbuf);
185 @@ -808,8 +822,34 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
186                 if (error)
187                         return error;
188  
189 -               snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
190 -                       rdbuf[0] >> 4, rdbuf[0] & 0x0F);
191 +               /* This "model identification" is not exact. Unfortunately
192 +                * not all firmwares for the ft5x06 put useful values in
193 +                * the identification registers.
194 +                */
195 +               switch (rdbuf[0]) {
196 +               case 0x35:   /* EDT EP0350M09 */
197 +               case 0x43:   /* EDT EP0430M09 */
198 +               case 0x50:   /* EDT EP0500M09 */
199 +               case 0x57:   /* EDT EP0570M09 */
200 +               case 0x70:   /* EDT EP0700M09 */
201 +                       tsdata->version = EDT_M09;
202 +                       snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
203 +                               rdbuf[0] >> 4, rdbuf[0] & 0x0F);
204 +                       break;
205 +               case 0xa1:   /* EDT EP1010ML00 */
206 +                       tsdata->version = EDT_M09;
207 +                       snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00",
208 +                               rdbuf[0] >> 4, rdbuf[0] & 0x0F);
209 +                       break;
210 +               case 0x5a:   /* Solomon Goldentek Display */
211 +                       snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
212 +                       break;
213 +               default:
214 +                       snprintf(model_name, EDT_NAME_LEN,
215 +                                "generic ft5x06 (%02x)",
216 +                                rdbuf[0]);
217 +                       break;
218 +               }
219         }
220  
221         return 0;
222 @@ -853,8 +893,16 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
223         if (reg_addr->reg_report_rate != NO_REGISTER)
224                 tsdata->report_rate = edt_ft5x06_register_read(tsdata,
225                                                 reg_addr->reg_report_rate);
226 -       tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x);
227 -       tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y);
228 +       if (tsdata->version == EDT_M06 ||
229 +           tsdata->version == EDT_M09) {
230 +               tsdata->num_x = edt_ft5x06_register_read(tsdata,
231 +                                                        reg_addr->reg_num_x);
232 +               tsdata->num_y = edt_ft5x06_register_read(tsdata,
233 +                                                        reg_addr->reg_num_y);
234 +       } else {
235 +               tsdata->num_x = -1;
236 +               tsdata->num_y = -1;
237 +       }
238  }
239  
240  static void
241 @@ -863,7 +911,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
242         struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
243  
244         switch (tsdata->version) {
245 -       case M06:
246 +       case EDT_M06:
247                 reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD;
248                 reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE;
249                 reg_addr->reg_gain = WORK_REGISTER_GAIN;
250 @@ -872,7 +920,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
251                 reg_addr->reg_num_y = WORK_REGISTER_NUM_Y;
252                 break;
253  
254 -       case M09:
255 +       case EDT_M09:
256                 reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
257                 reg_addr->reg_report_rate = NO_REGISTER;
258                 reg_addr->reg_gain = M09_REGISTER_GAIN;
259 @@ -880,6 +928,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
260                 reg_addr->reg_num_x = M09_REGISTER_NUM_X;
261                 reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
262                 break;
263 +
264 +       case GENERIC_FT:
265 +               /* this is a guesswork */
266 +               reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
267 +               reg_addr->reg_gain = M09_REGISTER_GAIN;
268 +               reg_addr->reg_offset = M09_REGISTER_OFFSET;
269 +               break;
270         }
271  }
272  
273 @@ -969,10 +1024,19 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
274         input->id.bustype = BUS_I2C;
275         input->dev.parent = &client->dev;
276  
277 -       input_set_abs_params(input, ABS_MT_POSITION_X,
278 -                            0, tsdata->num_x * 64 - 1, 0, 0);
279 -       input_set_abs_params(input, ABS_MT_POSITION_Y,
280 -                            0, tsdata->num_y * 64 - 1, 0, 0);
281 +       if (tsdata->version == EDT_M06 ||
282 +           tsdata->version == EDT_M09) {
283 +               input_set_abs_params(input, ABS_MT_POSITION_X,
284 +                                    0, tsdata->num_x * 64 - 1, 0, 0);
285 +               input_set_abs_params(input, ABS_MT_POSITION_Y,
286 +                                    0, tsdata->num_y * 64 - 1, 0, 0);
287 +       } else {
288 +               /* Unknown maximum values. Specify via devicetree */
289 +               input_set_abs_params(input, ABS_MT_POSITION_X,
290 +                                    0, 65535, 0, 0);
291 +               input_set_abs_params(input, ABS_MT_POSITION_Y,
292 +                                    0, 65535, 0, 0);
293 +       }
294  
295         touchscreen_parse_properties(input, true, &tsdata->prop);
296