Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/misc/ad714x.c
15109 views
1
/*
2
* AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A
3
*
4
* Copyright 2009 Analog Devices Inc.
5
*
6
* Licensed under the GPL-2 or later.
7
*/
8
9
#include <linux/device.h>
10
#include <linux/init.h>
11
#include <linux/input.h>
12
#include <linux/interrupt.h>
13
#include <linux/slab.h>
14
#include <linux/input/ad714x.h>
15
#include "ad714x.h"
16
17
#define AD714X_PWR_CTRL 0x0
18
#define AD714X_STG_CAL_EN_REG 0x1
19
#define AD714X_AMB_COMP_CTRL0_REG 0x2
20
#define AD714X_PARTID_REG 0x17
21
#define AD7142_PARTID 0xE620
22
#define AD7143_PARTID 0xE630
23
#define AD7147_PARTID 0x1470
24
#define AD7148_PARTID 0x1480
25
#define AD714X_STAGECFG_REG 0x80
26
#define AD714X_SYSCFG_REG 0x0
27
28
#define STG_LOW_INT_EN_REG 0x5
29
#define STG_HIGH_INT_EN_REG 0x6
30
#define STG_COM_INT_EN_REG 0x7
31
#define STG_LOW_INT_STA_REG 0x8
32
#define STG_HIGH_INT_STA_REG 0x9
33
#define STG_COM_INT_STA_REG 0xA
34
35
#define CDC_RESULT_S0 0xB
36
#define CDC_RESULT_S1 0xC
37
#define CDC_RESULT_S2 0xD
38
#define CDC_RESULT_S3 0xE
39
#define CDC_RESULT_S4 0xF
40
#define CDC_RESULT_S5 0x10
41
#define CDC_RESULT_S6 0x11
42
#define CDC_RESULT_S7 0x12
43
#define CDC_RESULT_S8 0x13
44
#define CDC_RESULT_S9 0x14
45
#define CDC_RESULT_S10 0x15
46
#define CDC_RESULT_S11 0x16
47
48
#define STAGE0_AMBIENT 0xF1
49
#define STAGE1_AMBIENT 0x115
50
#define STAGE2_AMBIENT 0x139
51
#define STAGE3_AMBIENT 0x15D
52
#define STAGE4_AMBIENT 0x181
53
#define STAGE5_AMBIENT 0x1A5
54
#define STAGE6_AMBIENT 0x1C9
55
#define STAGE7_AMBIENT 0x1ED
56
#define STAGE8_AMBIENT 0x211
57
#define STAGE9_AMBIENT 0x234
58
#define STAGE10_AMBIENT 0x259
59
#define STAGE11_AMBIENT 0x27D
60
61
#define PER_STAGE_REG_NUM 36
62
#define STAGE_NUM 12
63
#define STAGE_CFGREG_NUM 8
64
#define SYS_CFGREG_NUM 8
65
66
/*
67
* driver information which will be used to maintain the software flow
68
*/
69
enum ad714x_device_state { IDLE, JITTER, ACTIVE, SPACE };
70
71
struct ad714x_slider_drv {
72
int highest_stage;
73
int abs_pos;
74
int flt_pos;
75
enum ad714x_device_state state;
76
struct input_dev *input;
77
};
78
79
struct ad714x_wheel_drv {
80
int abs_pos;
81
int flt_pos;
82
int pre_highest_stage;
83
int highest_stage;
84
enum ad714x_device_state state;
85
struct input_dev *input;
86
};
87
88
struct ad714x_touchpad_drv {
89
int x_highest_stage;
90
int x_flt_pos;
91
int x_abs_pos;
92
int y_highest_stage;
93
int y_flt_pos;
94
int y_abs_pos;
95
int left_ep;
96
int left_ep_val;
97
int right_ep;
98
int right_ep_val;
99
int top_ep;
100
int top_ep_val;
101
int bottom_ep;
102
int bottom_ep_val;
103
enum ad714x_device_state state;
104
struct input_dev *input;
105
};
106
107
struct ad714x_button_drv {
108
enum ad714x_device_state state;
109
/*
110
* Unlike slider/wheel/touchpad, all buttons point to
111
* same input_dev instance
112
*/
113
struct input_dev *input;
114
};
115
116
struct ad714x_driver_data {
117
struct ad714x_slider_drv *slider;
118
struct ad714x_wheel_drv *wheel;
119
struct ad714x_touchpad_drv *touchpad;
120
struct ad714x_button_drv *button;
121
};
122
123
/*
124
* information to integrate all things which will be private data
125
* of spi/i2c device
126
*/
127
struct ad714x_chip {
128
unsigned short h_state;
129
unsigned short l_state;
130
unsigned short c_state;
131
unsigned short adc_reg[STAGE_NUM];
132
unsigned short amb_reg[STAGE_NUM];
133
unsigned short sensor_val[STAGE_NUM];
134
135
struct ad714x_platform_data *hw;
136
struct ad714x_driver_data *sw;
137
138
int irq;
139
struct device *dev;
140
ad714x_read_t read;
141
ad714x_write_t write;
142
143
struct mutex mutex;
144
145
unsigned product;
146
unsigned version;
147
};
148
149
static void ad714x_use_com_int(struct ad714x_chip *ad714x,
150
int start_stage, int end_stage)
151
{
152
unsigned short data;
153
unsigned short mask;
154
155
mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
156
157
ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
158
data |= 1 << end_stage;
159
ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
160
161
ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
162
data &= ~mask;
163
ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
164
}
165
166
static void ad714x_use_thr_int(struct ad714x_chip *ad714x,
167
int start_stage, int end_stage)
168
{
169
unsigned short data;
170
unsigned short mask;
171
172
mask = ((1 << (end_stage + 1)) - 1) - ((1 << start_stage) - 1);
173
174
ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data);
175
data &= ~(1 << end_stage);
176
ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data);
177
178
ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data);
179
data |= mask;
180
ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data);
181
}
182
183
static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x,
184
int start_stage, int end_stage)
185
{
186
int max_res = 0;
187
int max_idx = 0;
188
int i;
189
190
for (i = start_stage; i <= end_stage; i++) {
191
if (ad714x->sensor_val[i] > max_res) {
192
max_res = ad714x->sensor_val[i];
193
max_idx = i;
194
}
195
}
196
197
return max_idx;
198
}
199
200
static int ad714x_cal_abs_pos(struct ad714x_chip *ad714x,
201
int start_stage, int end_stage,
202
int highest_stage, int max_coord)
203
{
204
int a_param, b_param;
205
206
if (highest_stage == start_stage) {
207
a_param = ad714x->sensor_val[start_stage + 1];
208
b_param = ad714x->sensor_val[start_stage] +
209
ad714x->sensor_val[start_stage + 1];
210
} else if (highest_stage == end_stage) {
211
a_param = ad714x->sensor_val[end_stage] *
212
(end_stage - start_stage) +
213
ad714x->sensor_val[end_stage - 1] *
214
(end_stage - start_stage - 1);
215
b_param = ad714x->sensor_val[end_stage] +
216
ad714x->sensor_val[end_stage - 1];
217
} else {
218
a_param = ad714x->sensor_val[highest_stage] *
219
(highest_stage - start_stage) +
220
ad714x->sensor_val[highest_stage - 1] *
221
(highest_stage - start_stage - 1) +
222
ad714x->sensor_val[highest_stage + 1] *
223
(highest_stage - start_stage + 1);
224
b_param = ad714x->sensor_val[highest_stage] +
225
ad714x->sensor_val[highest_stage - 1] +
226
ad714x->sensor_val[highest_stage + 1];
227
}
228
229
return (max_coord / (end_stage - start_stage)) * a_param / b_param;
230
}
231
232
/*
233
* One button can connect to multi positive and negative of CDCs
234
* Multi-buttons can connect to same positive/negative of one CDC
235
*/
236
static void ad714x_button_state_machine(struct ad714x_chip *ad714x, int idx)
237
{
238
struct ad714x_button_plat *hw = &ad714x->hw->button[idx];
239
struct ad714x_button_drv *sw = &ad714x->sw->button[idx];
240
241
switch (sw->state) {
242
case IDLE:
243
if (((ad714x->h_state & hw->h_mask) == hw->h_mask) &&
244
((ad714x->l_state & hw->l_mask) == hw->l_mask)) {
245
dev_dbg(ad714x->dev, "button %d touched\n", idx);
246
input_report_key(sw->input, hw->keycode, 1);
247
input_sync(sw->input);
248
sw->state = ACTIVE;
249
}
250
break;
251
252
case ACTIVE:
253
if (((ad714x->h_state & hw->h_mask) != hw->h_mask) ||
254
((ad714x->l_state & hw->l_mask) != hw->l_mask)) {
255
dev_dbg(ad714x->dev, "button %d released\n", idx);
256
input_report_key(sw->input, hw->keycode, 0);
257
input_sync(sw->input);
258
sw->state = IDLE;
259
}
260
break;
261
262
default:
263
break;
264
}
265
}
266
267
/*
268
* The response of a sensor is defined by the absolute number of codes
269
* between the current CDC value and the ambient value.
270
*/
271
static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
272
{
273
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
274
int i;
275
276
for (i = hw->start_stage; i <= hw->end_stage; i++) {
277
ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
278
&ad714x->adc_reg[i]);
279
ad714x->read(ad714x->dev,
280
STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
281
&ad714x->amb_reg[i]);
282
283
ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] -
284
ad714x->amb_reg[i]);
285
}
286
}
287
288
static void ad714x_slider_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
289
{
290
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
291
struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
292
293
sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage,
294
hw->end_stage);
295
296
dev_dbg(ad714x->dev, "slider %d highest_stage:%d\n", idx,
297
sw->highest_stage);
298
}
299
300
/*
301
* The formulae are very straight forward. It uses the sensor with the
302
* highest response and the 2 adjacent ones.
303
* When Sensor 0 has the highest response, only sensor 0 and sensor 1
304
* are used in the calculations. Similarly when the last sensor has the
305
* highest response, only the last sensor and the second last sensors
306
* are used in the calculations.
307
*
308
* For i= idx_of_peak_Sensor-1 to i= idx_of_peak_Sensor+1
309
* v += Sensor response(i)*i
310
* w += Sensor response(i)
311
* POS=(Number_of_Positions_Wanted/(Number_of_Sensors_Used-1)) *(v/w)
312
*/
313
static void ad714x_slider_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
314
{
315
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
316
struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
317
318
sw->abs_pos = ad714x_cal_abs_pos(ad714x, hw->start_stage, hw->end_stage,
319
sw->highest_stage, hw->max_coord);
320
321
dev_dbg(ad714x->dev, "slider %d absolute position:%d\n", idx,
322
sw->abs_pos);
323
}
324
325
/*
326
* To minimise the Impact of the noise on the algorithm, ADI developed a
327
* routine that filters the CDC results after they have been read by the
328
* host processor.
329
* The filter used is an Infinite Input Response(IIR) filter implemented
330
* in firmware and attenuates the noise on the CDC results after they've
331
* been read by the host processor.
332
* Filtered_CDC_result = (Filtered_CDC_result * (10 - Coefficient) +
333
* Latest_CDC_result * Coefficient)/10
334
*/
335
static void ad714x_slider_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
336
{
337
struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
338
339
sw->flt_pos = (sw->flt_pos * (10 - 4) +
340
sw->abs_pos * 4)/10;
341
342
dev_dbg(ad714x->dev, "slider %d filter position:%d\n", idx,
343
sw->flt_pos);
344
}
345
346
static void ad714x_slider_use_com_int(struct ad714x_chip *ad714x, int idx)
347
{
348
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
349
350
ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage);
351
}
352
353
static void ad714x_slider_use_thr_int(struct ad714x_chip *ad714x, int idx)
354
{
355
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
356
357
ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage);
358
}
359
360
static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx)
361
{
362
struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx];
363
struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx];
364
unsigned short h_state, c_state;
365
unsigned short mask;
366
367
mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1);
368
369
h_state = ad714x->h_state & mask;
370
c_state = ad714x->c_state & mask;
371
372
switch (sw->state) {
373
case IDLE:
374
if (h_state) {
375
sw->state = JITTER;
376
/* In End of Conversion interrupt mode, the AD714X
377
* continuously generates hardware interrupts.
378
*/
379
ad714x_slider_use_com_int(ad714x, idx);
380
dev_dbg(ad714x->dev, "slider %d touched\n", idx);
381
}
382
break;
383
384
case JITTER:
385
if (c_state == mask) {
386
ad714x_slider_cal_sensor_val(ad714x, idx);
387
ad714x_slider_cal_highest_stage(ad714x, idx);
388
ad714x_slider_cal_abs_pos(ad714x, idx);
389
sw->flt_pos = sw->abs_pos;
390
sw->state = ACTIVE;
391
}
392
break;
393
394
case ACTIVE:
395
if (c_state == mask) {
396
if (h_state) {
397
ad714x_slider_cal_sensor_val(ad714x, idx);
398
ad714x_slider_cal_highest_stage(ad714x, idx);
399
ad714x_slider_cal_abs_pos(ad714x, idx);
400
ad714x_slider_cal_flt_pos(ad714x, idx);
401
input_report_abs(sw->input, ABS_X, sw->flt_pos);
402
input_report_key(sw->input, BTN_TOUCH, 1);
403
} else {
404
/* When the user lifts off the sensor, configure
405
* the AD714X back to threshold interrupt mode.
406
*/
407
ad714x_slider_use_thr_int(ad714x, idx);
408
sw->state = IDLE;
409
input_report_key(sw->input, BTN_TOUCH, 0);
410
dev_dbg(ad714x->dev, "slider %d released\n",
411
idx);
412
}
413
input_sync(sw->input);
414
}
415
break;
416
417
default:
418
break;
419
}
420
}
421
422
/*
423
* When the scroll wheel is activated, we compute the absolute position based
424
* on the sensor values. To calculate the position, we first determine the
425
* sensor that has the greatest response among the 8 sensors that constitutes
426
* the scrollwheel. Then we determined the 2 sensors on either sides of the
427
* sensor with the highest response and we apply weights to these sensors.
428
*/
429
static void ad714x_wheel_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
430
{
431
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
432
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
433
434
sw->pre_highest_stage = sw->highest_stage;
435
sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage,
436
hw->end_stage);
437
438
dev_dbg(ad714x->dev, "wheel %d highest_stage:%d\n", idx,
439
sw->highest_stage);
440
}
441
442
static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
443
{
444
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
445
int i;
446
447
for (i = hw->start_stage; i <= hw->end_stage; i++) {
448
ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
449
&ad714x->adc_reg[i]);
450
ad714x->read(ad714x->dev,
451
STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
452
&ad714x->amb_reg[i]);
453
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
454
ad714x->sensor_val[i] = ad714x->adc_reg[i] -
455
ad714x->amb_reg[i];
456
else
457
ad714x->sensor_val[i] = 0;
458
}
459
}
460
461
/*
462
* When the scroll wheel is activated, we compute the absolute position based
463
* on the sensor values. To calculate the position, we first determine the
464
* sensor that has the greatest response among the sensors that constitutes
465
* the scrollwheel. Then we determined the sensors on either sides of the
466
* sensor with the highest response and we apply weights to these sensors. The
467
* result of this computation gives us the mean value.
468
*/
469
470
static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
471
{
472
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
473
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
474
int stage_num = hw->end_stage - hw->start_stage + 1;
475
int first_before, highest, first_after;
476
int a_param, b_param;
477
478
first_before = (sw->highest_stage + stage_num - 1) % stage_num;
479
highest = sw->highest_stage;
480
first_after = (sw->highest_stage + stage_num + 1) % stage_num;
481
482
a_param = ad714x->sensor_val[highest] *
483
(highest - hw->start_stage) +
484
ad714x->sensor_val[first_before] *
485
(highest - hw->start_stage - 1) +
486
ad714x->sensor_val[first_after] *
487
(highest - hw->start_stage + 1);
488
b_param = ad714x->sensor_val[highest] +
489
ad714x->sensor_val[first_before] +
490
ad714x->sensor_val[first_after];
491
492
sw->abs_pos = ((hw->max_coord / (hw->end_stage - hw->start_stage)) *
493
a_param) / b_param;
494
495
if (sw->abs_pos > hw->max_coord)
496
sw->abs_pos = hw->max_coord;
497
else if (sw->abs_pos < 0)
498
sw->abs_pos = 0;
499
}
500
501
static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
502
{
503
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
504
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
505
if (((sw->pre_highest_stage == hw->end_stage) &&
506
(sw->highest_stage == hw->start_stage)) ||
507
((sw->pre_highest_stage == hw->start_stage) &&
508
(sw->highest_stage == hw->end_stage)))
509
sw->flt_pos = sw->abs_pos;
510
else
511
sw->flt_pos = ((sw->flt_pos * 30) + (sw->abs_pos * 71)) / 100;
512
513
if (sw->flt_pos > hw->max_coord)
514
sw->flt_pos = hw->max_coord;
515
}
516
517
static void ad714x_wheel_use_com_int(struct ad714x_chip *ad714x, int idx)
518
{
519
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
520
521
ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage);
522
}
523
524
static void ad714x_wheel_use_thr_int(struct ad714x_chip *ad714x, int idx)
525
{
526
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
527
528
ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage);
529
}
530
531
static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx)
532
{
533
struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx];
534
struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx];
535
unsigned short h_state, c_state;
536
unsigned short mask;
537
538
mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1);
539
540
h_state = ad714x->h_state & mask;
541
c_state = ad714x->c_state & mask;
542
543
switch (sw->state) {
544
case IDLE:
545
if (h_state) {
546
sw->state = JITTER;
547
/* In End of Conversion interrupt mode, the AD714X
548
* continuously generates hardware interrupts.
549
*/
550
ad714x_wheel_use_com_int(ad714x, idx);
551
dev_dbg(ad714x->dev, "wheel %d touched\n", idx);
552
}
553
break;
554
555
case JITTER:
556
if (c_state == mask) {
557
ad714x_wheel_cal_sensor_val(ad714x, idx);
558
ad714x_wheel_cal_highest_stage(ad714x, idx);
559
ad714x_wheel_cal_abs_pos(ad714x, idx);
560
sw->flt_pos = sw->abs_pos;
561
sw->state = ACTIVE;
562
}
563
break;
564
565
case ACTIVE:
566
if (c_state == mask) {
567
if (h_state) {
568
ad714x_wheel_cal_sensor_val(ad714x, idx);
569
ad714x_wheel_cal_highest_stage(ad714x, idx);
570
ad714x_wheel_cal_abs_pos(ad714x, idx);
571
ad714x_wheel_cal_flt_pos(ad714x, idx);
572
input_report_abs(sw->input, ABS_WHEEL,
573
sw->flt_pos);
574
input_report_key(sw->input, BTN_TOUCH, 1);
575
} else {
576
/* When the user lifts off the sensor, configure
577
* the AD714X back to threshold interrupt mode.
578
*/
579
ad714x_wheel_use_thr_int(ad714x, idx);
580
sw->state = IDLE;
581
input_report_key(sw->input, BTN_TOUCH, 0);
582
583
dev_dbg(ad714x->dev, "wheel %d released\n",
584
idx);
585
}
586
input_sync(sw->input);
587
}
588
break;
589
590
default:
591
break;
592
}
593
}
594
595
static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx)
596
{
597
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
598
int i;
599
600
for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) {
601
ad714x->read(ad714x->dev, CDC_RESULT_S0 + i,
602
&ad714x->adc_reg[i]);
603
ad714x->read(ad714x->dev,
604
STAGE0_AMBIENT + i * PER_STAGE_REG_NUM,
605
&ad714x->amb_reg[i]);
606
if (ad714x->adc_reg[i] > ad714x->amb_reg[i])
607
ad714x->sensor_val[i] = ad714x->adc_reg[i] -
608
ad714x->amb_reg[i];
609
else
610
ad714x->sensor_val[i] = 0;
611
}
612
}
613
614
static void touchpad_cal_highest_stage(struct ad714x_chip *ad714x, int idx)
615
{
616
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
617
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
618
619
sw->x_highest_stage = ad714x_cal_highest_stage(ad714x,
620
hw->x_start_stage, hw->x_end_stage);
621
sw->y_highest_stage = ad714x_cal_highest_stage(ad714x,
622
hw->y_start_stage, hw->y_end_stage);
623
624
dev_dbg(ad714x->dev,
625
"touchpad %d x_highest_stage:%d, y_highest_stage:%d\n",
626
idx, sw->x_highest_stage, sw->y_highest_stage);
627
}
628
629
/*
630
* If 2 fingers are touching the sensor then 2 peaks can be observed in the
631
* distribution.
632
* The arithmetic doesn't support to get absolute coordinates for multi-touch
633
* yet.
634
*/
635
static int touchpad_check_second_peak(struct ad714x_chip *ad714x, int idx)
636
{
637
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
638
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
639
int i;
640
641
for (i = hw->x_start_stage; i < sw->x_highest_stage; i++) {
642
if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1])
643
> (ad714x->sensor_val[i + 1] / 10))
644
return 1;
645
}
646
647
for (i = sw->x_highest_stage; i < hw->x_end_stage; i++) {
648
if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i])
649
> (ad714x->sensor_val[i] / 10))
650
return 1;
651
}
652
653
for (i = hw->y_start_stage; i < sw->y_highest_stage; i++) {
654
if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1])
655
> (ad714x->sensor_val[i + 1] / 10))
656
return 1;
657
}
658
659
for (i = sw->y_highest_stage; i < hw->y_end_stage; i++) {
660
if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i])
661
> (ad714x->sensor_val[i] / 10))
662
return 1;
663
}
664
665
return 0;
666
}
667
668
/*
669
* If only one finger is used to activate the touch pad then only 1 peak will be
670
* registered in the distribution. This peak and the 2 adjacent sensors will be
671
* used in the calculation of the absolute position. This will prevent hand
672
* shadows to affect the absolute position calculation.
673
*/
674
static void touchpad_cal_abs_pos(struct ad714x_chip *ad714x, int idx)
675
{
676
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
677
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
678
679
sw->x_abs_pos = ad714x_cal_abs_pos(ad714x, hw->x_start_stage,
680
hw->x_end_stage, sw->x_highest_stage, hw->x_max_coord);
681
sw->y_abs_pos = ad714x_cal_abs_pos(ad714x, hw->y_start_stage,
682
hw->y_end_stage, sw->y_highest_stage, hw->y_max_coord);
683
684
dev_dbg(ad714x->dev, "touchpad %d absolute position:(%d, %d)\n", idx,
685
sw->x_abs_pos, sw->y_abs_pos);
686
}
687
688
static void touchpad_cal_flt_pos(struct ad714x_chip *ad714x, int idx)
689
{
690
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
691
692
sw->x_flt_pos = (sw->x_flt_pos * (10 - 4) +
693
sw->x_abs_pos * 4)/10;
694
sw->y_flt_pos = (sw->y_flt_pos * (10 - 4) +
695
sw->y_abs_pos * 4)/10;
696
697
dev_dbg(ad714x->dev, "touchpad %d filter position:(%d, %d)\n",
698
idx, sw->x_flt_pos, sw->y_flt_pos);
699
}
700
701
/*
702
* To prevent distortion from showing in the absolute position, it is
703
* necessary to detect the end points. When endpoints are detected, the
704
* driver stops updating the status variables with absolute positions.
705
* End points are detected on the 4 edges of the touchpad sensor. The
706
* method to detect them is the same for all 4.
707
* To detect the end points, the firmware computes the difference in
708
* percent between the sensor on the edge and the adjacent one. The
709
* difference is calculated in percent in order to make the end point
710
* detection independent of the pressure.
711
*/
712
713
#define LEFT_END_POINT_DETECTION_LEVEL 550
714
#define RIGHT_END_POINT_DETECTION_LEVEL 750
715
#define LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL 850
716
#define TOP_END_POINT_DETECTION_LEVEL 550
717
#define BOTTOM_END_POINT_DETECTION_LEVEL 950
718
#define TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL 700
719
static int touchpad_check_endpoint(struct ad714x_chip *ad714x, int idx)
720
{
721
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
722
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
723
int percent_sensor_diff;
724
725
/* left endpoint detect */
726
percent_sensor_diff = (ad714x->sensor_val[hw->x_start_stage] -
727
ad714x->sensor_val[hw->x_start_stage + 1]) * 100 /
728
ad714x->sensor_val[hw->x_start_stage + 1];
729
if (!sw->left_ep) {
730
if (percent_sensor_diff >= LEFT_END_POINT_DETECTION_LEVEL) {
731
sw->left_ep = 1;
732
sw->left_ep_val =
733
ad714x->sensor_val[hw->x_start_stage + 1];
734
}
735
} else {
736
if ((percent_sensor_diff < LEFT_END_POINT_DETECTION_LEVEL) &&
737
(ad714x->sensor_val[hw->x_start_stage + 1] >
738
LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->left_ep_val))
739
sw->left_ep = 0;
740
}
741
742
/* right endpoint detect */
743
percent_sensor_diff = (ad714x->sensor_val[hw->x_end_stage] -
744
ad714x->sensor_val[hw->x_end_stage - 1]) * 100 /
745
ad714x->sensor_val[hw->x_end_stage - 1];
746
if (!sw->right_ep) {
747
if (percent_sensor_diff >= RIGHT_END_POINT_DETECTION_LEVEL) {
748
sw->right_ep = 1;
749
sw->right_ep_val =
750
ad714x->sensor_val[hw->x_end_stage - 1];
751
}
752
} else {
753
if ((percent_sensor_diff < RIGHT_END_POINT_DETECTION_LEVEL) &&
754
(ad714x->sensor_val[hw->x_end_stage - 1] >
755
LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->right_ep_val))
756
sw->right_ep = 0;
757
}
758
759
/* top endpoint detect */
760
percent_sensor_diff = (ad714x->sensor_val[hw->y_start_stage] -
761
ad714x->sensor_val[hw->y_start_stage + 1]) * 100 /
762
ad714x->sensor_val[hw->y_start_stage + 1];
763
if (!sw->top_ep) {
764
if (percent_sensor_diff >= TOP_END_POINT_DETECTION_LEVEL) {
765
sw->top_ep = 1;
766
sw->top_ep_val =
767
ad714x->sensor_val[hw->y_start_stage + 1];
768
}
769
} else {
770
if ((percent_sensor_diff < TOP_END_POINT_DETECTION_LEVEL) &&
771
(ad714x->sensor_val[hw->y_start_stage + 1] >
772
TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->top_ep_val))
773
sw->top_ep = 0;
774
}
775
776
/* bottom endpoint detect */
777
percent_sensor_diff = (ad714x->sensor_val[hw->y_end_stage] -
778
ad714x->sensor_val[hw->y_end_stage - 1]) * 100 /
779
ad714x->sensor_val[hw->y_end_stage - 1];
780
if (!sw->bottom_ep) {
781
if (percent_sensor_diff >= BOTTOM_END_POINT_DETECTION_LEVEL) {
782
sw->bottom_ep = 1;
783
sw->bottom_ep_val =
784
ad714x->sensor_val[hw->y_end_stage - 1];
785
}
786
} else {
787
if ((percent_sensor_diff < BOTTOM_END_POINT_DETECTION_LEVEL) &&
788
(ad714x->sensor_val[hw->y_end_stage - 1] >
789
TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->bottom_ep_val))
790
sw->bottom_ep = 0;
791
}
792
793
return sw->left_ep || sw->right_ep || sw->top_ep || sw->bottom_ep;
794
}
795
796
static void touchpad_use_com_int(struct ad714x_chip *ad714x, int idx)
797
{
798
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
799
800
ad714x_use_com_int(ad714x, hw->x_start_stage, hw->x_end_stage);
801
}
802
803
static void touchpad_use_thr_int(struct ad714x_chip *ad714x, int idx)
804
{
805
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
806
807
ad714x_use_thr_int(ad714x, hw->x_start_stage, hw->x_end_stage);
808
ad714x_use_thr_int(ad714x, hw->y_start_stage, hw->y_end_stage);
809
}
810
811
static void ad714x_touchpad_state_machine(struct ad714x_chip *ad714x, int idx)
812
{
813
struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx];
814
struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx];
815
unsigned short h_state, c_state;
816
unsigned short mask;
817
818
mask = (((1 << (hw->x_end_stage + 1)) - 1) -
819
((1 << hw->x_start_stage) - 1)) +
820
(((1 << (hw->y_end_stage + 1)) - 1) -
821
((1 << hw->y_start_stage) - 1));
822
823
h_state = ad714x->h_state & mask;
824
c_state = ad714x->c_state & mask;
825
826
switch (sw->state) {
827
case IDLE:
828
if (h_state) {
829
sw->state = JITTER;
830
/* In End of Conversion interrupt mode, the AD714X
831
* continuously generates hardware interrupts.
832
*/
833
touchpad_use_com_int(ad714x, idx);
834
dev_dbg(ad714x->dev, "touchpad %d touched\n", idx);
835
}
836
break;
837
838
case JITTER:
839
if (c_state == mask) {
840
touchpad_cal_sensor_val(ad714x, idx);
841
touchpad_cal_highest_stage(ad714x, idx);
842
if ((!touchpad_check_second_peak(ad714x, idx)) &&
843
(!touchpad_check_endpoint(ad714x, idx))) {
844
dev_dbg(ad714x->dev,
845
"touchpad%d, 2 fingers or endpoint\n",
846
idx);
847
touchpad_cal_abs_pos(ad714x, idx);
848
sw->x_flt_pos = sw->x_abs_pos;
849
sw->y_flt_pos = sw->y_abs_pos;
850
sw->state = ACTIVE;
851
}
852
}
853
break;
854
855
case ACTIVE:
856
if (c_state == mask) {
857
if (h_state) {
858
touchpad_cal_sensor_val(ad714x, idx);
859
touchpad_cal_highest_stage(ad714x, idx);
860
if ((!touchpad_check_second_peak(ad714x, idx))
861
&& (!touchpad_check_endpoint(ad714x, idx))) {
862
touchpad_cal_abs_pos(ad714x, idx);
863
touchpad_cal_flt_pos(ad714x, idx);
864
input_report_abs(sw->input, ABS_X,
865
sw->x_flt_pos);
866
input_report_abs(sw->input, ABS_Y,
867
sw->y_flt_pos);
868
input_report_key(sw->input, BTN_TOUCH,
869
1);
870
}
871
} else {
872
/* When the user lifts off the sensor, configure
873
* the AD714X back to threshold interrupt mode.
874
*/
875
touchpad_use_thr_int(ad714x, idx);
876
sw->state = IDLE;
877
input_report_key(sw->input, BTN_TOUCH, 0);
878
dev_dbg(ad714x->dev, "touchpad %d released\n",
879
idx);
880
}
881
input_sync(sw->input);
882
}
883
break;
884
885
default:
886
break;
887
}
888
}
889
890
static int ad714x_hw_detect(struct ad714x_chip *ad714x)
891
{
892
unsigned short data;
893
894
ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data);
895
switch (data & 0xFFF0) {
896
case AD7142_PARTID:
897
ad714x->product = 0x7142;
898
ad714x->version = data & 0xF;
899
dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n",
900
ad714x->version);
901
return 0;
902
903
case AD7143_PARTID:
904
ad714x->product = 0x7143;
905
ad714x->version = data & 0xF;
906
dev_info(ad714x->dev, "found AD7143 captouch, rev:%d\n",
907
ad714x->version);
908
return 0;
909
910
case AD7147_PARTID:
911
ad714x->product = 0x7147;
912
ad714x->version = data & 0xF;
913
dev_info(ad714x->dev, "found AD7147(A) captouch, rev:%d\n",
914
ad714x->version);
915
return 0;
916
917
case AD7148_PARTID:
918
ad714x->product = 0x7148;
919
ad714x->version = data & 0xF;
920
dev_info(ad714x->dev, "found AD7148 captouch, rev:%d\n",
921
ad714x->version);
922
return 0;
923
924
default:
925
dev_err(ad714x->dev,
926
"fail to detect AD714X captouch, read ID is %04x\n",
927
data);
928
return -ENODEV;
929
}
930
}
931
932
static void ad714x_hw_init(struct ad714x_chip *ad714x)
933
{
934
int i, j;
935
unsigned short reg_base;
936
unsigned short data;
937
938
/* configuration CDC and interrupts */
939
940
for (i = 0; i < STAGE_NUM; i++) {
941
reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM;
942
for (j = 0; j < STAGE_CFGREG_NUM; j++)
943
ad714x->write(ad714x->dev, reg_base + j,
944
ad714x->hw->stage_cfg_reg[i][j]);
945
}
946
947
for (i = 0; i < SYS_CFGREG_NUM; i++)
948
ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i,
949
ad714x->hw->sys_cfg_reg[i]);
950
for (i = 0; i < SYS_CFGREG_NUM; i++)
951
ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i,
952
&data);
953
954
ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF);
955
956
/* clear all interrupts */
957
ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
958
ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
959
ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
960
}
961
962
static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
963
{
964
struct ad714x_chip *ad714x = data;
965
int i;
966
967
mutex_lock(&ad714x->mutex);
968
969
ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state);
970
ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state);
971
ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state);
972
973
for (i = 0; i < ad714x->hw->button_num; i++)
974
ad714x_button_state_machine(ad714x, i);
975
for (i = 0; i < ad714x->hw->slider_num; i++)
976
ad714x_slider_state_machine(ad714x, i);
977
for (i = 0; i < ad714x->hw->wheel_num; i++)
978
ad714x_wheel_state_machine(ad714x, i);
979
for (i = 0; i < ad714x->hw->touchpad_num; i++)
980
ad714x_touchpad_state_machine(ad714x, i);
981
982
mutex_unlock(&ad714x->mutex);
983
984
return IRQ_HANDLED;
985
}
986
987
#define MAX_DEVICE_NUM 8
988
struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
989
ad714x_read_t read, ad714x_write_t write)
990
{
991
int i, alloc_idx;
992
int error;
993
struct input_dev *input[MAX_DEVICE_NUM];
994
995
struct ad714x_platform_data *plat_data = dev->platform_data;
996
struct ad714x_chip *ad714x;
997
void *drv_mem;
998
999
struct ad714x_button_drv *bt_drv;
1000
struct ad714x_slider_drv *sd_drv;
1001
struct ad714x_wheel_drv *wl_drv;
1002
struct ad714x_touchpad_drv *tp_drv;
1003
1004
1005
if (irq <= 0) {
1006
dev_err(dev, "IRQ not configured!\n");
1007
error = -EINVAL;
1008
goto err_out;
1009
}
1010
1011
if (dev->platform_data == NULL) {
1012
dev_err(dev, "platform data for ad714x doesn't exist\n");
1013
error = -EINVAL;
1014
goto err_out;
1015
}
1016
1017
ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
1018
sizeof(*sd_drv) * plat_data->slider_num +
1019
sizeof(*wl_drv) * plat_data->wheel_num +
1020
sizeof(*tp_drv) * plat_data->touchpad_num +
1021
sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
1022
if (!ad714x) {
1023
error = -ENOMEM;
1024
goto err_out;
1025
}
1026
1027
ad714x->hw = plat_data;
1028
1029
drv_mem = ad714x + 1;
1030
ad714x->sw = drv_mem;
1031
drv_mem += sizeof(*ad714x->sw);
1032
ad714x->sw->slider = sd_drv = drv_mem;
1033
drv_mem += sizeof(*sd_drv) * ad714x->hw->slider_num;
1034
ad714x->sw->wheel = wl_drv = drv_mem;
1035
drv_mem += sizeof(*wl_drv) * ad714x->hw->wheel_num;
1036
ad714x->sw->touchpad = tp_drv = drv_mem;
1037
drv_mem += sizeof(*tp_drv) * ad714x->hw->touchpad_num;
1038
ad714x->sw->button = bt_drv = drv_mem;
1039
drv_mem += sizeof(*bt_drv) * ad714x->hw->button_num;
1040
1041
ad714x->read = read;
1042
ad714x->write = write;
1043
ad714x->irq = irq;
1044
ad714x->dev = dev;
1045
1046
error = ad714x_hw_detect(ad714x);
1047
if (error)
1048
goto err_free_mem;
1049
1050
/* initialize and request sw/hw resources */
1051
1052
ad714x_hw_init(ad714x);
1053
mutex_init(&ad714x->mutex);
1054
1055
/*
1056
* Allocate and register AD714X input device
1057
*/
1058
alloc_idx = 0;
1059
1060
/* a slider uses one input_dev instance */
1061
if (ad714x->hw->slider_num > 0) {
1062
struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
1063
1064
for (i = 0; i < ad714x->hw->slider_num; i++) {
1065
sd_drv[i].input = input[alloc_idx] = input_allocate_device();
1066
if (!input[alloc_idx]) {
1067
error = -ENOMEM;
1068
goto err_free_dev;
1069
}
1070
1071
__set_bit(EV_ABS, input[alloc_idx]->evbit);
1072
__set_bit(EV_KEY, input[alloc_idx]->evbit);
1073
__set_bit(ABS_X, input[alloc_idx]->absbit);
1074
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1075
input_set_abs_params(input[alloc_idx],
1076
ABS_X, 0, sd_plat->max_coord, 0, 0);
1077
1078
input[alloc_idx]->id.bustype = bus_type;
1079
input[alloc_idx]->id.product = ad714x->product;
1080
input[alloc_idx]->id.version = ad714x->version;
1081
input[alloc_idx]->name = "ad714x_captouch_slider";
1082
input[alloc_idx]->dev.parent = dev;
1083
1084
error = input_register_device(input[alloc_idx]);
1085
if (error)
1086
goto err_free_dev;
1087
1088
alloc_idx++;
1089
}
1090
}
1091
1092
/* a wheel uses one input_dev instance */
1093
if (ad714x->hw->wheel_num > 0) {
1094
struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
1095
1096
for (i = 0; i < ad714x->hw->wheel_num; i++) {
1097
wl_drv[i].input = input[alloc_idx] = input_allocate_device();
1098
if (!input[alloc_idx]) {
1099
error = -ENOMEM;
1100
goto err_free_dev;
1101
}
1102
1103
__set_bit(EV_KEY, input[alloc_idx]->evbit);
1104
__set_bit(EV_ABS, input[alloc_idx]->evbit);
1105
__set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
1106
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1107
input_set_abs_params(input[alloc_idx],
1108
ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
1109
1110
input[alloc_idx]->id.bustype = bus_type;
1111
input[alloc_idx]->id.product = ad714x->product;
1112
input[alloc_idx]->id.version = ad714x->version;
1113
input[alloc_idx]->name = "ad714x_captouch_wheel";
1114
input[alloc_idx]->dev.parent = dev;
1115
1116
error = input_register_device(input[alloc_idx]);
1117
if (error)
1118
goto err_free_dev;
1119
1120
alloc_idx++;
1121
}
1122
}
1123
1124
/* a touchpad uses one input_dev instance */
1125
if (ad714x->hw->touchpad_num > 0) {
1126
struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
1127
1128
for (i = 0; i < ad714x->hw->touchpad_num; i++) {
1129
tp_drv[i].input = input[alloc_idx] = input_allocate_device();
1130
if (!input[alloc_idx]) {
1131
error = -ENOMEM;
1132
goto err_free_dev;
1133
}
1134
1135
__set_bit(EV_ABS, input[alloc_idx]->evbit);
1136
__set_bit(EV_KEY, input[alloc_idx]->evbit);
1137
__set_bit(ABS_X, input[alloc_idx]->absbit);
1138
__set_bit(ABS_Y, input[alloc_idx]->absbit);
1139
__set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
1140
input_set_abs_params(input[alloc_idx],
1141
ABS_X, 0, tp_plat->x_max_coord, 0, 0);
1142
input_set_abs_params(input[alloc_idx],
1143
ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
1144
1145
input[alloc_idx]->id.bustype = bus_type;
1146
input[alloc_idx]->id.product = ad714x->product;
1147
input[alloc_idx]->id.version = ad714x->version;
1148
input[alloc_idx]->name = "ad714x_captouch_pad";
1149
input[alloc_idx]->dev.parent = dev;
1150
1151
error = input_register_device(input[alloc_idx]);
1152
if (error)
1153
goto err_free_dev;
1154
1155
alloc_idx++;
1156
}
1157
}
1158
1159
/* all buttons use one input node */
1160
if (ad714x->hw->button_num > 0) {
1161
struct ad714x_button_plat *bt_plat = ad714x->hw->button;
1162
1163
input[alloc_idx] = input_allocate_device();
1164
if (!input[alloc_idx]) {
1165
error = -ENOMEM;
1166
goto err_free_dev;
1167
}
1168
1169
__set_bit(EV_KEY, input[alloc_idx]->evbit);
1170
for (i = 0; i < ad714x->hw->button_num; i++) {
1171
bt_drv[i].input = input[alloc_idx];
1172
__set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
1173
}
1174
1175
input[alloc_idx]->id.bustype = bus_type;
1176
input[alloc_idx]->id.product = ad714x->product;
1177
input[alloc_idx]->id.version = ad714x->version;
1178
input[alloc_idx]->name = "ad714x_captouch_button";
1179
input[alloc_idx]->dev.parent = dev;
1180
1181
error = input_register_device(input[alloc_idx]);
1182
if (error)
1183
goto err_free_dev;
1184
1185
alloc_idx++;
1186
}
1187
1188
error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
1189
plat_data->irqflags ?
1190
plat_data->irqflags : IRQF_TRIGGER_FALLING,
1191
"ad714x_captouch", ad714x);
1192
if (error) {
1193
dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
1194
goto err_unreg_dev;
1195
}
1196
1197
return ad714x;
1198
1199
err_free_dev:
1200
dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
1201
input_free_device(input[alloc_idx]);
1202
err_unreg_dev:
1203
while (--alloc_idx >= 0)
1204
input_unregister_device(input[alloc_idx]);
1205
err_free_mem:
1206
kfree(ad714x);
1207
err_out:
1208
return ERR_PTR(error);
1209
}
1210
EXPORT_SYMBOL(ad714x_probe);
1211
1212
void ad714x_remove(struct ad714x_chip *ad714x)
1213
{
1214
struct ad714x_platform_data *hw = ad714x->hw;
1215
struct ad714x_driver_data *sw = ad714x->sw;
1216
int i;
1217
1218
free_irq(ad714x->irq, ad714x);
1219
1220
/* unregister and free all input devices */
1221
1222
for (i = 0; i < hw->slider_num; i++)
1223
input_unregister_device(sw->slider[i].input);
1224
1225
for (i = 0; i < hw->wheel_num; i++)
1226
input_unregister_device(sw->wheel[i].input);
1227
1228
for (i = 0; i < hw->touchpad_num; i++)
1229
input_unregister_device(sw->touchpad[i].input);
1230
1231
if (hw->button_num)
1232
input_unregister_device(sw->button[0].input);
1233
1234
kfree(ad714x);
1235
}
1236
EXPORT_SYMBOL(ad714x_remove);
1237
1238
#ifdef CONFIG_PM
1239
int ad714x_disable(struct ad714x_chip *ad714x)
1240
{
1241
unsigned short data;
1242
1243
dev_dbg(ad714x->dev, "%s enter\n", __func__);
1244
1245
mutex_lock(&ad714x->mutex);
1246
1247
data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3;
1248
ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data);
1249
1250
mutex_unlock(&ad714x->mutex);
1251
1252
return 0;
1253
}
1254
EXPORT_SYMBOL(ad714x_disable);
1255
1256
int ad714x_enable(struct ad714x_chip *ad714x)
1257
{
1258
unsigned short data;
1259
1260
dev_dbg(ad714x->dev, "%s enter\n", __func__);
1261
1262
mutex_lock(&ad714x->mutex);
1263
1264
/* resume to non-shutdown mode */
1265
1266
ad714x->write(ad714x->dev, AD714X_PWR_CTRL,
1267
ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]);
1268
1269
/* make sure the interrupt output line is not low level after resume,
1270
* otherwise we will get no chance to enter falling-edge irq again
1271
*/
1272
1273
ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data);
1274
ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data);
1275
ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data);
1276
1277
mutex_unlock(&ad714x->mutex);
1278
1279
return 0;
1280
}
1281
EXPORT_SYMBOL(ad714x_enable);
1282
#endif
1283
1284
MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor Driver");
1285
MODULE_AUTHOR("Barry Song <[email protected]>");
1286
MODULE_LICENSE("GPL");
1287
1288