1 /*
2 * cyttsp5_mt_common.c
3 * Parade TrueTouch(TM) Standard Product V5 Multi-Touch Reports Module.
4 * For use with Parade touchscreen controllers.
5 * Supported parts include:
6 * CYTMA5XX
7 * CYTMA448
8 * CYTMA445A
9 * CYTT21XXX
10 * CYTT31XXX
11 *
12 * Copyright (C) 2015 Parade Technologies
13 * Copyright (C) 2012-2015 Cypress Semiconductor
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * version 2, and only version 2, as published by the
18 * Free Software Foundation.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
26 *
27 */
28
29 #include "cyttsp5_regs.h"
30
31 #define CYTTSP5_MT_NAME "cyttsp5_mt"
32
33 #define MT_PARAM_SIGNAL(md, sig_ost) PARAM_SIGNAL(md->pdata->frmwrk, sig_ost)
34 #define MT_PARAM_MIN(md, sig_ost) PARAM_MIN(md->pdata->frmwrk, sig_ost)
35 #define MT_PARAM_MAX(md, sig_ost) PARAM_MAX(md->pdata->frmwrk, sig_ost)
36 #define MT_PARAM_FUZZ(md, sig_ost) PARAM_FUZZ(md->pdata->frmwrk, sig_ost)
37 #define MT_PARAM_FLAT(md, sig_ost) PARAM_FLAT(md->pdata->frmwrk, sig_ost)
38
39 static int screen_max_x = 1872;
40 static int screen_max_y = 1404;
41 static int revert_x_flag = 0;
42 static int revert_y_flag = 0;
43 static int exchange_x_y_flag = 0;
44
cyttsp5_mt_lift_all(struct cyttsp5_mt_data * md)45 static void cyttsp5_mt_lift_all(struct cyttsp5_mt_data *md)
46 {
47 int max = md->si->tch_abs[CY_TCH_T].max;
48
49 if (md->num_prv_rec != 0) {
50 if (md->mt_function.report_slot_liftoff)
51 md->mt_function.report_slot_liftoff(md, max);
52 input_sync(md->input);
53 md->num_prv_rec = 0;
54 }
55 }
56
cyttsp5_get_touch_axis(struct cyttsp5_mt_data * md,int * axis,int size,int max,u8 * xy_data,int bofs)57 static void cyttsp5_get_touch_axis(struct cyttsp5_mt_data *md,
58 int *axis, int size, int max, u8 *xy_data, int bofs)
59 {
60 int nbyte;
61 int next;
62
63 for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
64 parade_debug(md->dev, DEBUG_LEVEL_2,
65 "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
66 __func__, *axis, *axis, size, max, xy_data, next,
67 xy_data[next], xy_data[next], bofs);
68 *axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
69 next++;
70 }
71
72 *axis &= max - 1;
73
74 parade_debug(md->dev, DEBUG_LEVEL_2,
75 "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
76 __func__, *axis, *axis, size, max, xy_data, next,
77 xy_data[next], xy_data[next]);
78 }
79
cyttsp5_get_touch_hdr(struct cyttsp5_mt_data * md,struct cyttsp5_touch * touch,u8 * xy_mode)80 static void cyttsp5_get_touch_hdr(struct cyttsp5_mt_data *md,
81 struct cyttsp5_touch *touch, u8 *xy_mode)
82 {
83 struct device *dev = md->dev;
84 struct cyttsp5_sysinfo *si = md->si;
85 enum cyttsp5_tch_hdr hdr;
86
87 for (hdr = CY_TCH_TIME; hdr < CY_TCH_NUM_HDR; hdr++) {
88 if (!si->tch_hdr[hdr].report)
89 continue;
90 cyttsp5_get_touch_axis(md, &touch->hdr[hdr],
91 si->tch_hdr[hdr].size,
92 si->tch_hdr[hdr].max,
93 xy_mode + si->tch_hdr[hdr].ofs,
94 si->tch_hdr[hdr].bofs);
95 parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
96 __func__, cyttsp5_tch_hdr_string[hdr],
97 touch->hdr[hdr], touch->hdr[hdr]);
98 }
99
100 parade_debug(dev, DEBUG_LEVEL_1,
101 "%s: time=%X tch_num=%d lo=%d noise=%d counter=%d\n",
102 __func__,
103 touch->hdr[CY_TCH_TIME],
104 touch->hdr[CY_TCH_NUM],
105 touch->hdr[CY_TCH_LO],
106 touch->hdr[CY_TCH_NOISE],
107 touch->hdr[CY_TCH_COUNTER]);
108 }
109
cyttsp5_get_touch_record(struct cyttsp5_mt_data * md,struct cyttsp5_touch * touch,u8 * xy_data)110 static void cyttsp5_get_touch_record(struct cyttsp5_mt_data *md,
111 struct cyttsp5_touch *touch, u8 *xy_data)
112 {
113 struct device *dev = md->dev;
114 struct cyttsp5_sysinfo *si = md->si;
115 enum cyttsp5_tch_abs abs;
116
117 for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) {
118 if (!si->tch_abs[abs].report)
119 continue;
120 cyttsp5_get_touch_axis(md, &touch->abs[abs],
121 si->tch_abs[abs].size,
122 si->tch_abs[abs].max,
123 xy_data + si->tch_abs[abs].ofs,
124 si->tch_abs[abs].bofs);
125 parade_debug(dev, DEBUG_LEVEL_2, "%s: get %s=%04X(%d)\n",
126 __func__, cyttsp5_tch_abs_string[abs],
127 touch->abs[abs], touch->abs[abs]);
128 }
129 }
130
cyttsp5_mt_process_touch(struct cyttsp5_mt_data * md,struct cyttsp5_touch * touch)131 static void cyttsp5_mt_process_touch(struct cyttsp5_mt_data *md,
132 struct cyttsp5_touch *touch)
133 {
134 struct device *dev = md->dev;
135 struct cyttsp5_sysinfo *si = md->si;
136 int tmp;
137 bool flipped;
138
139
140 /* Orientation is signed */
141 touch->abs[CY_TCH_OR] = (int8_t)touch->abs[CY_TCH_OR];
142
143 if (md->pdata->flags & CY_MT_FLAG_FLIP) {
144 tmp = touch->abs[CY_TCH_X];
145 touch->abs[CY_TCH_X] = touch->abs[CY_TCH_Y];
146 touch->abs[CY_TCH_Y] = tmp;
147 if (touch->abs[CY_TCH_OR] > 0)
148 touch->abs[CY_TCH_OR] =
149 md->or_max - touch->abs[CY_TCH_OR];
150 else
151 touch->abs[CY_TCH_OR] =
152 md->or_min - touch->abs[CY_TCH_OR];
153 flipped = true;
154 } else
155 flipped = false;
156
157 if (md->pdata->flags & CY_MT_FLAG_INV_X) {
158 if (flipped)
159 touch->abs[CY_TCH_X] = si->sensing_conf_data.res_y -
160 touch->abs[CY_TCH_X];
161 else
162 touch->abs[CY_TCH_X] = si->sensing_conf_data.res_x -
163 touch->abs[CY_TCH_X];
164 touch->abs[CY_TCH_OR] *= -1;
165 }
166 if (md->pdata->flags & CY_MT_FLAG_INV_Y) {
167 if (flipped)
168 touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_x -
169 touch->abs[CY_TCH_Y];
170 else
171 touch->abs[CY_TCH_Y] = si->sensing_conf_data.res_y -
172 touch->abs[CY_TCH_Y];
173 touch->abs[CY_TCH_OR] *= -1;
174 }
175
176 /* Convert MAJOR/MINOR from mm to resolution */
177 tmp = touch->abs[CY_TCH_MAJ] * 100 * si->sensing_conf_data.res_x;
178 touch->abs[CY_TCH_MAJ] = tmp / si->sensing_conf_data.len_x;
179 tmp = touch->abs[CY_TCH_MIN] * 100 * si->sensing_conf_data.res_x;
180 touch->abs[CY_TCH_MIN] = tmp / si->sensing_conf_data.len_x;
181
182 parade_debug(dev, DEBUG_LEVEL_2, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n",
183 __func__, flipped ? "true" : "false",
184 md->pdata->flags & CY_MT_FLAG_INV_X ? "true" : "false",
185 md->pdata->flags & CY_MT_FLAG_INV_Y ? "true" : "false",
186 touch->abs[CY_TCH_X], touch->abs[CY_TCH_X],
187 touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]);
188 }
189
cyttsp5_report_event(struct cyttsp5_mt_data * md,int event,int value)190 static void cyttsp5_report_event(struct cyttsp5_mt_data *md, int event,
191 int value)
192 {
193 int sig = MT_PARAM_SIGNAL(md, event);
194
195 if(sig == ABS_MT_POSITION_X || sig == ABS_MT_POSITION_Y){
196 //printk("******cyttsp5_report_event sig=0x%x,%x,%x, value=%d\n", sig, ABS_MT_POSITION_X, ABS_MT_POSITION_Y, value);
197 //printk("******cyttsp5_report_event x=%d, y=%d,z=%d\n", revert_x_flag,
198 //revert_y_flag, exchange_x_y_flag);
199
200 if(exchange_x_y_flag ){
201 if(sig == ABS_MT_POSITION_X)
202 {
203 sig = ABS_MT_POSITION_Y;
204 if(value > screen_max_y)
205 value = screen_max_y;
206 }
207 else
208 {
209 sig = ABS_MT_POSITION_X;
210 if(value > screen_max_x)
211 value = screen_max_x;
212 }
213 }
214
215 if(revert_x_flag && sig == ABS_MT_POSITION_X){
216 value = screen_max_x - value;
217 }
218
219 if(revert_y_flag && sig == ABS_MT_POSITION_Y){
220 value = screen_max_y - value;
221 }
222 //printk("******cyttsp5_report_event 111 [%s], value=%d\n",
223 // sig == ABS_MT_POSITION_X ? "x" : "y", value);
224 }
225
226 if (sig != CY_IGNORE_VALUE)
227 input_report_abs(md->input, sig, value);
228
229 }
230
cyttsp5_get_mt_touches(struct cyttsp5_mt_data * md,struct cyttsp5_touch * tch,int num_cur_tch)231 static void cyttsp5_get_mt_touches(struct cyttsp5_mt_data *md,
232 struct cyttsp5_touch *tch, int num_cur_tch)
233 {
234 struct device *dev = md->dev;
235 struct cyttsp5_sysinfo *si = md->si;
236 int sig;
237 int i, j, t = 0;
238 DECLARE_BITMAP(ids, si->tch_abs[CY_TCH_T].max);
239 int mt_sync_count = 0;
240 u8 *tch_addr;
241
242 bitmap_zero(ids, si->tch_abs[CY_TCH_T].max);
243 memset(tch->abs, 0, sizeof(tch->abs));
244 //printk("***cyttsp5_get_mt_touches num_cur_tch=%x, count=%d\n", num_cur_tch,
245 // mt_sync_count);
246
247 for (i = 0; i < num_cur_tch; i++) {
248 tch_addr = si->xy_data + (i * si->desc.tch_record_size);
249 cyttsp5_get_touch_record(md, tch, tch_addr);
250
251 /* Discard proximity event */
252 if (tch->abs[CY_TCH_O] == CY_OBJ_PROXIMITY) {
253 parade_debug(dev, DEBUG_LEVEL_2, "%s: Discarding proximity event\n",
254 __func__);
255 continue;
256 }
257
258 /* Validate track_id */
259 t = tch->abs[CY_TCH_T];
260 if (t < md->t_min || t > md->t_max) {
261 dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n",
262 __func__, i, t, md->t_max);
263 if (md->mt_function.input_sync)
264 md->mt_function.input_sync(md->input);
265 mt_sync_count++;
266 continue;
267 }
268
269 /* Lift-off */
270 if (tch->abs[CY_TCH_E] == CY_EV_LIFTOFF) {
271 parade_debug(dev, DEBUG_LEVEL_1, "%s: t=%d e=%d lift-off\n",
272 __func__, t, tch->abs[CY_TCH_E]);
273 goto cyttsp5_get_mt_touches_pr_tch;
274 }
275
276 /* Process touch */
277 cyttsp5_mt_process_touch(md, tch);
278
279 /* use 0 based track id's */
280 t -= md->t_min;
281
282 sig = MT_PARAM_SIGNAL(md, CY_ABS_ID_OST);
283 if (sig != CY_IGNORE_VALUE) {
284 if (md->mt_function.input_report)
285 md->mt_function.input_report(md->input, sig,
286 t, tch->abs[CY_TCH_O]);
287 __set_bit(t, ids);
288 }
289
290 /* If touch type is hover, send P as distance, reset P */
291 if (tch->abs[CY_TCH_O] == CY_OBJ_HOVER) {
292 /* CY_ABS_D_OST signal must be in touch framework */
293 cyttsp5_report_event(md, CY_ABS_D_OST,
294 tch->abs[CY_TCH_P]);
295 tch->abs[CY_TCH_P] = 0;
296 } else
297 cyttsp5_report_event(md, CY_ABS_D_OST, 0);
298
299
300 /* all devices: position and pressure fields */
301 for (j = 0; j <= CY_ABS_W_OST; j++) {
302 if (!si->tch_abs[j].report)
303 continue;
304 cyttsp5_report_event(md, CY_ABS_X_OST + j,
305 tch->abs[CY_TCH_X + j]);
306 }
307
308 /* Get the extended touch fields */
309 for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) {
310 if (!si->tch_abs[CY_ABS_MAJ_OST + j].report)
311 continue;
312 cyttsp5_report_event(md, CY_ABS_MAJ_OST + j,
313 tch->abs[CY_TCH_MAJ + j]);
314 }
315 if (md->mt_function.input_sync)
316 md->mt_function.input_sync(md->input);
317 mt_sync_count++;
318 //printk("***cyttsp5_get_mt_touches sync=0x%x, count=%d\n", md->mt_function.input_sync,
319 // mt_sync_count);
320
321 cyttsp5_get_mt_touches_pr_tch:
322 parade_debug(dev, DEBUG_LEVEL_1,
323 "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d obj=%d tip=%d\n",
324 __func__, t,
325 tch->abs[CY_TCH_X],
326 tch->abs[CY_TCH_Y],
327 tch->abs[CY_TCH_P],
328 tch->abs[CY_TCH_MAJ],
329 tch->abs[CY_TCH_MIN],
330 tch->abs[CY_TCH_OR],
331 tch->abs[CY_TCH_E],
332 tch->abs[CY_TCH_O],
333 tch->abs[CY_TCH_TIP]);
334 }
335
336 if (md->mt_function.final_sync)
337 md->mt_function.final_sync(md->input,
338 si->tch_abs[CY_TCH_T].max, mt_sync_count, ids);
339
340 md->num_prv_rec = num_cur_tch;
341 }
342
343 /* read xy_data for all current touches */
cyttsp5_xy_worker(struct cyttsp5_mt_data * md)344 static int cyttsp5_xy_worker(struct cyttsp5_mt_data *md)
345 {
346 struct device *dev = md->dev;
347 struct cyttsp5_sysinfo *si = md->si;
348 int max_tch = si->sensing_conf_data.max_tch;
349 struct cyttsp5_touch tch;
350 u8 num_cur_tch;
351 int rc = 0;
352
353 cyttsp5_get_touch_hdr(md, &tch, si->xy_mode + 3);
354
355 num_cur_tch = tch.hdr[CY_TCH_NUM];
356 if (num_cur_tch > max_tch) {
357 dev_err(dev, "%s: Num touch err detected (n=%d)\n",
358 __func__, num_cur_tch);
359 num_cur_tch = max_tch;
360 }
361
362 if (tch.hdr[CY_TCH_LO]) {
363 parade_debug(dev, DEBUG_LEVEL_1, "%s: Large area detected\n",
364 __func__);
365 if (md->pdata->flags & CY_MT_FLAG_NO_TOUCH_ON_LO)
366 num_cur_tch = 0;
367 }
368
369 if (num_cur_tch == 0 && md->num_prv_rec == 0)
370 goto cyttsp5_xy_worker_exit;
371
372 /* extract xy_data for all currently reported touches */
373 parade_debug(dev, DEBUG_LEVEL_2, "%s: extract data num_cur_tch=%d\n",
374 __func__, num_cur_tch);
375 if (num_cur_tch)
376 cyttsp5_get_mt_touches(md, &tch, num_cur_tch);
377 else
378 cyttsp5_mt_lift_all(md);
379
380 rc = 0;
381
382 cyttsp5_xy_worker_exit:
383 return rc;
384 }
385
cyttsp5_mt_send_dummy_event(struct cyttsp5_core_data * cd,struct cyttsp5_mt_data * md)386 static void cyttsp5_mt_send_dummy_event(struct cyttsp5_core_data *cd,
387 struct cyttsp5_mt_data *md)
388 {
389 #ifndef EASYWAKE_TSG6
390 /* TSG5 EasyWake */
391 unsigned long ids = 0;
392
393 /* for easy wakeup */
394 if (md->mt_function.input_report)
395 md->mt_function.input_report(md->input, ABS_MT_TRACKING_ID,
396 0, CY_OBJ_STANDARD_FINGER);
397 if (md->mt_function.input_sync)
398 md->mt_function.input_sync(md->input);
399 if (md->mt_function.final_sync)
400 md->mt_function.final_sync(md->input, 0, 1, &ids);
401 if (md->mt_function.report_slot_liftoff)
402 md->mt_function.report_slot_liftoff(md, 1);
403 if (md->mt_function.final_sync)
404 md->mt_function.final_sync(md->input, 1, 1, &ids);
405 #else
406 /* TSG6 FW1.3 and above only. TSG6 FW1.0 - 1.2 does not */
407 /* support EasyWake, and this function will not be called */
408 u8 key_value;
409
410 switch (cd->gesture_id) {
411 case GESTURE_DOUBLE_TAP:
412 key_value = KEY_F1;
413 break;
414 case GESTURE_TWO_FINGERS_SLIDE:
415 key_value = KEY_F2;
416 break;
417 case GESTURE_TOUCH_DETECTED:
418 key_value = KEY_F3;
419 break;
420 case GESTURE_PUSH_BUTTON:
421 key_value = KEY_F4;
422 break;
423 case GESTURE_SINGLE_SLIDE_DE_TX:
424 key_value = KEY_F5;
425 break;
426 case GESTURE_SINGLE_SLIDE_IN_TX:
427 key_value = KEY_F6;
428 break;
429 case GESTURE_SINGLE_SLIDE_DE_RX:
430 key_value = KEY_F7;
431 break;
432 case GESTURE_SINGLE_SLIDE_IN_RX:
433 key_value = KEY_F8;
434 break;
435 default:
436 break;
437 }
438
439 input_report_key(md->input, key_value, 1);
440 mdelay(10);
441 input_report_key(md->input, key_value, 0);
442 input_sync(md->input);
443 #endif
444 }
445
cyttsp5_mt_attention(struct device * dev)446 static int cyttsp5_mt_attention(struct device *dev)
447 {
448 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
449 struct cyttsp5_mt_data *md = &cd->md;
450 int rc;
451
452 if (md->si->xy_mode[2] != md->si->desc.tch_report_id)
453 return 0;
454
455 /* core handles handshake */
456 mutex_lock(&md->mt_lock);
457 rc = cyttsp5_xy_worker(md);
458 mutex_unlock(&md->mt_lock);
459 if (rc < 0)
460 dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc);
461
462 return rc;
463 }
464
cyttsp5_mt_wake_attention(struct device * dev)465 static int cyttsp5_mt_wake_attention(struct device *dev)
466 {
467 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
468 struct cyttsp5_mt_data *md = &cd->md;
469
470 mutex_lock(&md->mt_lock);
471 cyttsp5_mt_send_dummy_event(cd, md);
472 mutex_unlock(&md->mt_lock);
473 return 0;
474 }
475
cyttsp5_startup_attention(struct device * dev)476 static int cyttsp5_startup_attention(struct device *dev)
477 {
478 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
479 struct cyttsp5_mt_data *md = &cd->md;
480
481 mutex_lock(&md->mt_lock);
482 cyttsp5_mt_lift_all(md);
483 mutex_unlock(&md->mt_lock);
484
485 return 0;
486 }
487
cyttsp5_mt_suspend_attention(struct device * dev)488 static int cyttsp5_mt_suspend_attention(struct device *dev)
489 {
490 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
491 struct cyttsp5_mt_data *md = &cd->md;
492
493 mutex_lock(&md->mt_lock);
494 cyttsp5_mt_lift_all(md);
495 md->is_suspended = true;
496 mutex_unlock(&md->mt_lock);
497
498 pm_runtime_put(dev);
499
500 return 0;
501 }
502
cyttsp5_mt_resume_attention(struct device * dev)503 static int cyttsp5_mt_resume_attention(struct device *dev)
504 {
505 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
506 struct cyttsp5_mt_data *md = &cd->md;
507
508 pm_runtime_get(dev);
509
510 mutex_lock(&md->mt_lock);
511 md->is_suspended = false;
512 mutex_unlock(&md->mt_lock);
513
514 return 0;
515 }
516
cyttsp5_mt_open(struct input_dev * input)517 static int cyttsp5_mt_open(struct input_dev *input)
518 {
519 struct device *dev = input->dev.parent;
520 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
521 struct cyttsp5_mt_data *md = &cd->md;
522
523 pm_runtime_get_sync(dev);
524
525 mutex_lock(&md->mt_lock);
526 md->is_suspended = false;
527 mutex_unlock(&md->mt_lock);
528
529 parade_debug(dev, DEBUG_LEVEL_2, "%s: setup subscriptions\n", __func__);
530
531 /* set up touch call back */
532 _cyttsp5_subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
533 cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
534
535 /* set up startup call back */
536 _cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
537 cyttsp5_startup_attention, 0);
538
539 /* set up wakeup call back */
540 _cyttsp5_subscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
541 cyttsp5_mt_wake_attention, 0);
542
543 /* set up suspend call back */
544 _cyttsp5_subscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
545 cyttsp5_mt_suspend_attention, 0);
546
547 /* set up resume call back */
548 _cyttsp5_subscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
549 cyttsp5_mt_resume_attention, 0);
550
551 return 0;
552 }
553
cyttsp5_mt_close(struct input_dev * input)554 static void cyttsp5_mt_close(struct input_dev *input)
555 {
556 struct device *dev = input->dev.parent;
557 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
558 struct cyttsp5_mt_data *md = &cd->md;
559
560 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_MT_NAME,
561 cyttsp5_mt_attention, CY_MODE_OPERATIONAL);
562
563 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
564 cyttsp5_startup_attention, 0);
565
566 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_WAKE, CYTTSP5_MT_NAME,
567 cyttsp5_mt_wake_attention, 0);
568
569 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_SUSPEND, CYTTSP5_MT_NAME,
570 cyttsp5_mt_suspend_attention, 0);
571
572 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_RESUME, CYTTSP5_MT_NAME,
573 cyttsp5_mt_resume_attention, 0);
574
575 mutex_lock(&md->mt_lock);
576 if (!md->is_suspended) {
577 pm_runtime_put(dev);
578 md->is_suspended = true;
579 }
580 mutex_unlock(&md->mt_lock);
581 }
582
cyttsp5_setup_input_device(struct device * dev)583 static int cyttsp5_setup_input_device(struct device *dev)
584 {
585 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
586 struct cyttsp5_mt_data *md = &cd->md;
587 int signal = CY_IGNORE_VALUE;
588 int max_x, max_y, max_p, min, max;
589 int max_x_tmp, max_y_tmp;
590 int i;
591 int rc;
592
593 parade_debug(dev, DEBUG_LEVEL_2, "%s: Initialize event signals\n",
594 __func__);
595 __set_bit(EV_ABS, md->input->evbit);
596 __set_bit(EV_REL, md->input->evbit);
597 __set_bit(EV_KEY, md->input->evbit);
598 #ifdef INPUT_PROP_DIRECT
599 __set_bit(INPUT_PROP_DIRECT, md->input->propbit);
600 #endif
601
602 /* If virtualkeys enabled, don't use all screen */
603 if (md->pdata->flags & CY_MT_FLAG_VKEYS) {
604 max_x_tmp = md->pdata->vkeys_x;
605 max_y_tmp = md->pdata->vkeys_y;
606 } else {
607 max_x_tmp = md->si->sensing_conf_data.res_x;
608 max_y_tmp = md->si->sensing_conf_data.res_y;
609 }
610
611 /* get maximum values from the sysinfo data */
612 if (md->pdata->flags & CY_MT_FLAG_FLIP) {
613 max_x = max_y_tmp - 1;
614 max_y = max_x_tmp - 1;
615 } else {
616 max_x = max_x_tmp - 1;
617 max_y = max_y_tmp - 1;
618 }
619 max_p = md->si->sensing_conf_data.max_z;
620
621 /* set event signal capabilities */
622 for (i = 0; i < NUM_SIGNALS(md->pdata->frmwrk); i++) {
623 signal = MT_PARAM_SIGNAL(md, i);
624 if (signal != CY_IGNORE_VALUE) {
625 __set_bit(signal, md->input->absbit);
626
627 min = MT_PARAM_MIN(md, i);
628 max = MT_PARAM_MAX(md, i);
629 if (i == CY_ABS_ID_OST) {
630 /* shift track ids down to start at 0 */
631 max = max - min;
632 min = min - min;
633 } else if (i == CY_ABS_X_OST)
634 max = max_x;
635 else if (i == CY_ABS_Y_OST)
636 max = max_y;
637 else if (i == CY_ABS_P_OST)
638 max = max_p;
639 /*change x-y max value*/
640 if(signal == ABS_MT_POSITION_X)
641 max = screen_max_x;
642 if(signal == ABS_MT_POSITION_Y)
643 max = screen_max_y;
644
645 input_set_abs_params(md->input, signal, min, max,
646 MT_PARAM_FUZZ(md, i), MT_PARAM_FLAT(md, i));
647 parade_debug(dev, DEBUG_LEVEL_1,
648 "%s: register signal=%02X min=%d max=%d\n",
649 __func__, signal, min, max);
650 }
651 }
652
653 md->or_min = MT_PARAM_MIN(md, CY_ABS_OR_OST);
654 md->or_max = MT_PARAM_MAX(md, CY_ABS_OR_OST);
655
656 md->t_min = MT_PARAM_MIN(md, CY_ABS_ID_OST);
657 md->t_max = MT_PARAM_MAX(md, CY_ABS_ID_OST);
658
659 rc = md->mt_function.input_register_device(md->input,
660 md->si->tch_abs[CY_TCH_T].max);
661 if (rc < 0)
662 dev_err(dev, "%s: Error, failed register input device r=%d\n",
663 __func__, rc);
664 else
665 md->input_device_registered = true;
666
667 #ifdef EASYWAKE_TSG6
668 input_set_capability(md->input, EV_KEY, KEY_F1);
669 input_set_capability(md->input, EV_KEY, KEY_F2);
670 input_set_capability(md->input, EV_KEY, KEY_F3);
671 input_set_capability(md->input, EV_KEY, KEY_F4);
672 input_set_capability(md->input, EV_KEY, KEY_F5);
673 input_set_capability(md->input, EV_KEY, KEY_F6);
674 input_set_capability(md->input, EV_KEY, KEY_F7);
675 input_set_capability(md->input, EV_KEY, KEY_F8);
676 #endif
677 return rc;
678 }
679
cyttsp5_setup_input_attention(struct device * dev)680 static int cyttsp5_setup_input_attention(struct device *dev)
681 {
682 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
683 struct cyttsp5_mt_data *md = &cd->md;
684 int rc;
685
686 md->si = _cyttsp5_request_sysinfo(dev);
687 if (!md->si)
688 return -EINVAL;
689
690 rc = cyttsp5_setup_input_device(dev);
691
692 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_MT_NAME,
693 cyttsp5_setup_input_attention, 0);
694
695 return rc;
696 }
697
cyttsp5_mt_probe(struct device * dev)698 int cyttsp5_mt_probe(struct device *dev)
699 {
700 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
701 struct cyttsp5_mt_data *md = &cd->md;
702 struct cyttsp5_cydata *cydata = &cd->sysinfo.cydata;
703 struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
704 struct cyttsp5_mt_platform_data *mt_pdata;
705 int rc = 0;
706
707 //printk("*****cyttsp5_mt_probe\n");
708 if (!pdata || !pdata->mt_pdata) {
709 dev_err(dev, "%s: Missing platform data\n", __func__);
710 rc = -ENODEV;
711 goto error_no_pdata;
712 }
713 mt_pdata = pdata->mt_pdata;
714 revert_x_flag = mt_pdata->swap_x;
715 revert_y_flag = mt_pdata->swap_y;
716 exchange_x_y_flag = mt_pdata->xy_exchange;
717 if (exchange_x_y_flag) {
718 int tmp = screen_max_x;
719 screen_max_x = screen_max_y;
720 screen_max_y = tmp;
721 }
722
723 //printk("*****cyttsp5_mt_probe 1111\n");
724 cyttsp5_init_function_ptrs(md);
725 //printk("*****cyttsp5_mt_probe 2222\n");
726
727 mutex_init(&md->mt_lock);
728 md->dev = dev;
729 md->pdata = mt_pdata;
730
731 /* Create the input device and register it. */
732 parade_debug(dev, DEBUG_LEVEL_2,
733 "%s: Create the input device and register it\n", __func__);
734 md->input = input_allocate_device();
735 if (!md->input) {
736 dev_err(dev, "%s: Error, failed to allocate input device\n",
737 __func__);
738 rc = -ENODEV;
739 goto error_alloc_failed;
740 }
741
742 md->input->id.version = cydata->fw_ver_conf;
743 if (md->pdata->inp_dev_name)
744 md->input->name = md->pdata->inp_dev_name;
745 else
746 md->input->name = CYTTSP5_MT_NAME;
747 scnprintf(md->phys, sizeof(md->phys), "%s/input%d", dev_name(dev),
748 cd->phys_num++);
749 md->input->phys = md->phys;
750 md->input->dev.parent = md->dev;
751 md->input->open = cyttsp5_mt_open;
752 md->input->close = cyttsp5_mt_close;
753 input_set_drvdata(md->input, md);
754
755 /* get sysinfo */
756 md->si = _cyttsp5_request_sysinfo(dev);
757
758 if (md->si) {
759 rc = cyttsp5_setup_input_device(dev);
760 if (rc)
761 goto error_init_input;
762 } else {
763 dev_err(dev, "%s: Fail get sysinfo pointer from core p=%p\n",
764 __func__, md->si);
765 _cyttsp5_subscribe_attention(dev, CY_ATTEN_STARTUP,
766 CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
767 }
768
769 return 0;
770
771 error_init_input:
772 input_free_device(md->input);
773 error_alloc_failed:
774 error_no_pdata:
775 dev_err(dev, "%s failed.\n", __func__);
776 return rc;
777 }
778
cyttsp5_mt_release(struct device * dev)779 int cyttsp5_mt_release(struct device *dev)
780 {
781 struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
782 struct cyttsp5_mt_data *md = &cd->md;
783
784 if (md->input_device_registered) {
785 input_unregister_device(md->input);
786 } else {
787 input_free_device(md->input);
788 _cyttsp5_unsubscribe_attention(dev, CY_ATTEN_STARTUP,
789 CYTTSP5_MT_NAME, cyttsp5_setup_input_attention, 0);
790 }
791
792 return 0;
793 }
794