diff options
Diffstat (limited to 'drivers/input')
49 files changed, 3894 insertions, 308 deletions
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index cb150a1dbaff..54fce56c8023 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c | |||
@@ -88,10 +88,13 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, | |||
88 | goto err_mem; | 88 | goto err_mem; |
89 | } | 89 | } |
90 | 90 | ||
91 | /* Mark slots as 'unused' */ | 91 | /* Mark slots as 'inactive' */ |
92 | for (i = 0; i < num_slots; i++) | 92 | for (i = 0; i < num_slots; i++) |
93 | input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); | 93 | input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); |
94 | 94 | ||
95 | /* Mark slots as 'unused' */ | ||
96 | mt->frame = 1; | ||
97 | |||
95 | dev->mt = mt; | 98 | dev->mt = mt; |
96 | return 0; | 99 | return 0; |
97 | err_mem: | 100 | err_mem: |
@@ -365,27 +368,35 @@ static void input_mt_set_slots(struct input_mt *mt, | |||
365 | int *slots, int num_pos) | 368 | int *slots, int num_pos) |
366 | { | 369 | { |
367 | struct input_mt_slot *s; | 370 | struct input_mt_slot *s; |
368 | int *w = mt->red, *p; | 371 | int *w = mt->red, j; |
369 | 372 | ||
370 | for (p = slots; p != slots + num_pos; p++) | 373 | for (j = 0; j != num_pos; j++) |
371 | *p = -1; | 374 | slots[j] = -1; |
372 | 375 | ||
373 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { | 376 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { |
374 | if (!input_mt_is_active(s)) | 377 | if (!input_mt_is_active(s)) |
375 | continue; | 378 | continue; |
376 | for (p = slots; p != slots + num_pos; p++) | 379 | |
377 | if (*w++ < 0) | 380 | for (j = 0; j != num_pos; j++) { |
378 | *p = s - mt->slots; | 381 | if (w[j] < 0) { |
382 | slots[j] = s - mt->slots; | ||
383 | break; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | w += num_pos; | ||
379 | } | 388 | } |
380 | 389 | ||
381 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { | 390 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { |
382 | if (input_mt_is_active(s)) | 391 | if (input_mt_is_active(s)) |
383 | continue; | 392 | continue; |
384 | for (p = slots; p != slots + num_pos; p++) | 393 | |
385 | if (*p < 0) { | 394 | for (j = 0; j != num_pos; j++) { |
386 | *p = s - mt->slots; | 395 | if (slots[j] < 0) { |
396 | slots[j] = s - mt->slots; | ||
387 | break; | 397 | break; |
388 | } | 398 | } |
399 | } | ||
389 | } | 400 | } |
390 | } | 401 | } |
391 | 402 | ||
@@ -439,6 +450,8 @@ EXPORT_SYMBOL(input_mt_assign_slots); | |||
439 | * set the key on the first unused slot and return. | 450 | * set the key on the first unused slot and return. |
440 | * | 451 | * |
441 | * If no available slot can be found, -1 is returned. | 452 | * If no available slot can be found, -1 is returned. |
453 | * Note that for this function to work properly, input_mt_sync_frame() has | ||
454 | * to be called at each frame. | ||
442 | */ | 455 | */ |
443 | int input_mt_get_slot_by_key(struct input_dev *dev, int key) | 456 | int input_mt_get_slot_by_key(struct input_dev *dev, int key) |
444 | { | 457 | { |
@@ -453,7 +466,7 @@ int input_mt_get_slot_by_key(struct input_dev *dev, int key) | |||
453 | return s - mt->slots; | 466 | return s - mt->slots; |
454 | 467 | ||
455 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) | 468 | for (s = mt->slots; s != mt->slots + mt->num_slots; s++) |
456 | if (!input_mt_is_active(s)) { | 469 | if (!input_mt_is_active(s) && !input_mt_is_used(mt, s)) { |
457 | s->key = key; | 470 | s->key = key; |
458 | return s - mt->slots; | 471 | return s - mt->slots; |
459 | } | 472 | } |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a89ba7cb96f1..106fbac7f8c5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -588,6 +588,16 @@ config KEYBOARD_DAVINCI | |||
588 | To compile this driver as a module, choose M here: the | 588 | To compile this driver as a module, choose M here: the |
589 | module will be called davinci_keyscan. | 589 | module will be called davinci_keyscan. |
590 | 590 | ||
591 | config KEYBOARD_IPAQ_MICRO | ||
592 | tristate "Buttons on Micro SoC (iPaq h3100,h3600,h3700)" | ||
593 | depends on MFD_IPAQ_MICRO | ||
594 | help | ||
595 | Say Y to enable support for the buttons attached to | ||
596 | Micro peripheral controller on iPAQ h3100/h3600/h3700 | ||
597 | |||
598 | To compile this driver as a module, choose M here: the | ||
599 | module will be called ipaq-micro-keys. | ||
600 | |||
591 | config KEYBOARD_OMAP | 601 | config KEYBOARD_OMAP |
592 | tristate "TI OMAP keypad support" | 602 | tristate "TI OMAP keypad support" |
593 | depends on ARCH_OMAP1 | 603 | depends on ARCH_OMAP1 |
@@ -686,4 +696,15 @@ config KEYBOARD_CAP11XX | |||
686 | To compile this driver as a module, choose M here: the | 696 | To compile this driver as a module, choose M here: the |
687 | module will be called cap11xx. | 697 | module will be called cap11xx. |
688 | 698 | ||
699 | config KEYBOARD_BCM | ||
700 | tristate "Broadcom keypad driver" | ||
701 | depends on OF && HAVE_CLK | ||
702 | select INPUT_MATRIXKMAP | ||
703 | default ARCH_BCM_CYGNUS | ||
704 | help | ||
705 | Say Y here if you want to use Broadcom keypad. | ||
706 | |||
707 | To compile this driver as a module, choose M here: the | ||
708 | module will be called bcm-keypad. | ||
709 | |||
689 | endif | 710 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 470767884bd8..df28d5553c05 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o | |||
10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
13 | obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o | ||
13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 14 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
14 | obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o | 15 | obj-$(CONFIG_KEYBOARD_CAP11XX) += cap11xx.o |
15 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o | 16 | obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o |
@@ -23,6 +24,7 @@ obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o | |||
23 | obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o | 24 | obj-$(CONFIG_KEYBOARD_TCA8418) += tca8418_keypad.o |
24 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 25 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
25 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 26 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
27 | obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o | ||
26 | obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o | 28 | obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o |
27 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | 29 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o |
28 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | 30 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 387c51f4b4e4..ec876b5b1382 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -1653,6 +1653,12 @@ static int __init atkbd_deactivate_fixup(const struct dmi_system_id *id) | |||
1653 | return 1; | 1653 | return 1; |
1654 | } | 1654 | } |
1655 | 1655 | ||
1656 | /* | ||
1657 | * NOTE: do not add any more "force release" quirks to this table. The | ||
1658 | * task of adjusting list of keys that should be "released" automatically | ||
1659 | * by the driver is now delegated to userspace tools, such as udev, so | ||
1660 | * submit such quirks there. | ||
1661 | */ | ||
1656 | static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { | 1662 | static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { |
1657 | { | 1663 | { |
1658 | .matches = { | 1664 | .matches = { |
diff --git a/drivers/input/keyboard/bcm-keypad.c b/drivers/input/keyboard/bcm-keypad.c new file mode 100644 index 000000000000..86a8b723ae15 --- /dev/null +++ b/drivers/input/keyboard/bcm-keypad.c | |||
@@ -0,0 +1,458 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/gfp.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/input/matrix_keypad.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/stddef.h> | ||
25 | #include <linux/types.h> | ||
26 | |||
27 | #define DEFAULT_CLK_HZ 31250 | ||
28 | #define MAX_ROWS 8 | ||
29 | #define MAX_COLS 8 | ||
30 | |||
31 | /* Register/field definitions */ | ||
32 | #define KPCR_OFFSET 0x00000080 | ||
33 | #define KPCR_MODE 0x00000002 | ||
34 | #define KPCR_MODE_SHIFT 1 | ||
35 | #define KPCR_MODE_MASK 1 | ||
36 | #define KPCR_ENABLE 0x00000001 | ||
37 | #define KPCR_STATUSFILTERENABLE 0x00008000 | ||
38 | #define KPCR_STATUSFILTERTYPE_SHIFT 12 | ||
39 | #define KPCR_COLFILTERENABLE 0x00000800 | ||
40 | #define KPCR_COLFILTERTYPE_SHIFT 8 | ||
41 | #define KPCR_ROWWIDTH_SHIFT 20 | ||
42 | #define KPCR_COLUMNWIDTH_SHIFT 16 | ||
43 | |||
44 | #define KPIOR_OFFSET 0x00000084 | ||
45 | #define KPIOR_ROWOCONTRL_SHIFT 24 | ||
46 | #define KPIOR_ROWOCONTRL_MASK 0xFF000000 | ||
47 | #define KPIOR_COLUMNOCONTRL_SHIFT 16 | ||
48 | #define KPIOR_COLUMNOCONTRL_MASK 0x00FF0000 | ||
49 | #define KPIOR_COLUMN_IO_DATA_SHIFT 0 | ||
50 | |||
51 | #define KPEMR0_OFFSET 0x00000090 | ||
52 | #define KPEMR1_OFFSET 0x00000094 | ||
53 | #define KPEMR2_OFFSET 0x00000098 | ||
54 | #define KPEMR3_OFFSET 0x0000009C | ||
55 | #define KPEMR_EDGETYPE_BOTH 3 | ||
56 | |||
57 | #define KPSSR0_OFFSET 0x000000A0 | ||
58 | #define KPSSR1_OFFSET 0x000000A4 | ||
59 | #define KPSSRN_OFFSET(reg_n) (KPSSR0_OFFSET + 4 * (reg_n)) | ||
60 | #define KPIMR0_OFFSET 0x000000B0 | ||
61 | #define KPIMR1_OFFSET 0x000000B4 | ||
62 | #define KPICR0_OFFSET 0x000000B8 | ||
63 | #define KPICR1_OFFSET 0x000000BC | ||
64 | #define KPICRN_OFFSET(reg_n) (KPICR0_OFFSET + 4 * (reg_n)) | ||
65 | #define KPISR0_OFFSET 0x000000C0 | ||
66 | #define KPISR1_OFFSET 0x000000C4 | ||
67 | |||
68 | #define KPCR_STATUSFILTERTYPE_MAX 7 | ||
69 | #define KPCR_COLFILTERTYPE_MAX 7 | ||
70 | |||
71 | /* Macros to determine the row/column from a bit that is set in SSR0/1. */ | ||
72 | #define BIT_TO_ROW_SSRN(bit_nr, reg_n) (((bit_nr) >> 3) + 4 * (reg_n)) | ||
73 | #define BIT_TO_COL(bit_nr) ((bit_nr) % 8) | ||
74 | |||
75 | /* Structure representing various run-time entities */ | ||
76 | struct bcm_kp { | ||
77 | void __iomem *base; | ||
78 | int irq; | ||
79 | struct clk *clk; | ||
80 | struct input_dev *input_dev; | ||
81 | unsigned long last_state[2]; | ||
82 | unsigned int n_rows; | ||
83 | unsigned int n_cols; | ||
84 | u32 kpcr; | ||
85 | u32 kpior; | ||
86 | u32 kpemr; | ||
87 | u32 imr0_val; | ||
88 | u32 imr1_val; | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * Returns the keycode from the input device keymap given the row and | ||
93 | * column. | ||
94 | */ | ||
95 | static int bcm_kp_get_keycode(struct bcm_kp *kp, int row, int col) | ||
96 | { | ||
97 | unsigned int row_shift = get_count_order(kp->n_cols); | ||
98 | unsigned short *keymap = kp->input_dev->keycode; | ||
99 | |||
100 | return keymap[MATRIX_SCAN_CODE(row, col, row_shift)]; | ||
101 | } | ||
102 | |||
103 | static void bcm_kp_report_keys(struct bcm_kp *kp, int reg_num, int pull_mode) | ||
104 | { | ||
105 | unsigned long state, change; | ||
106 | int bit_nr; | ||
107 | int key_press; | ||
108 | int row, col; | ||
109 | unsigned int keycode; | ||
110 | |||
111 | /* Clear interrupts */ | ||
112 | writel(0xFFFFFFFF, kp->base + KPICRN_OFFSET(reg_num)); | ||
113 | |||
114 | state = readl(kp->base + KPSSRN_OFFSET(reg_num)); | ||
115 | change = kp->last_state[reg_num] ^ state; | ||
116 | kp->last_state[reg_num] = state; | ||
117 | |||
118 | for_each_set_bit(bit_nr, &change, BITS_PER_LONG) { | ||
119 | key_press = state & BIT(bit_nr); | ||
120 | /* The meaning of SSR register depends on pull mode. */ | ||
121 | key_press = pull_mode ? !key_press : key_press; | ||
122 | row = BIT_TO_ROW_SSRN(bit_nr, reg_num); | ||
123 | col = BIT_TO_COL(bit_nr); | ||
124 | keycode = bcm_kp_get_keycode(kp, row, col); | ||
125 | input_report_key(kp->input_dev, keycode, key_press); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static irqreturn_t bcm_kp_isr_thread(int irq, void *dev_id) | ||
130 | { | ||
131 | struct bcm_kp *kp = dev_id; | ||
132 | int pull_mode = (kp->kpcr >> KPCR_MODE_SHIFT) & KPCR_MODE_MASK; | ||
133 | int reg_num; | ||
134 | |||
135 | for (reg_num = 0; reg_num <= 1; reg_num++) | ||
136 | bcm_kp_report_keys(kp, reg_num, pull_mode); | ||
137 | |||
138 | input_sync(kp->input_dev); | ||
139 | |||
140 | return IRQ_HANDLED; | ||
141 | } | ||
142 | |||
143 | static int bcm_kp_start(struct bcm_kp *kp) | ||
144 | { | ||
145 | int error; | ||
146 | |||
147 | if (kp->clk) { | ||
148 | error = clk_prepare_enable(kp->clk); | ||
149 | if (error) | ||
150 | return error; | ||
151 | } | ||
152 | |||
153 | writel(kp->kpior, kp->base + KPIOR_OFFSET); | ||
154 | |||
155 | writel(kp->imr0_val, kp->base + KPIMR0_OFFSET); | ||
156 | writel(kp->imr1_val, kp->base + KPIMR1_OFFSET); | ||
157 | |||
158 | writel(kp->kpemr, kp->base + KPEMR0_OFFSET); | ||
159 | writel(kp->kpemr, kp->base + KPEMR1_OFFSET); | ||
160 | writel(kp->kpemr, kp->base + KPEMR2_OFFSET); | ||
161 | writel(kp->kpemr, kp->base + KPEMR3_OFFSET); | ||
162 | |||
163 | writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET); | ||
164 | writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET); | ||
165 | |||
166 | kp->last_state[0] = readl(kp->base + KPSSR0_OFFSET); | ||
167 | kp->last_state[0] = readl(kp->base + KPSSR1_OFFSET); | ||
168 | |||
169 | writel(kp->kpcr | KPCR_ENABLE, kp->base + KPCR_OFFSET); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void bcm_kp_stop(const struct bcm_kp *kp) | ||
175 | { | ||
176 | u32 val; | ||
177 | |||
178 | val = readl(kp->base + KPCR_OFFSET); | ||
179 | val &= ~KPCR_ENABLE; | ||
180 | writel(0, kp->base + KPCR_OFFSET); | ||
181 | writel(0, kp->base + KPIMR0_OFFSET); | ||
182 | writel(0, kp->base + KPIMR1_OFFSET); | ||
183 | writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET); | ||
184 | writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET); | ||
185 | |||
186 | if (kp->clk) | ||
187 | clk_disable_unprepare(kp->clk); | ||
188 | } | ||
189 | |||
190 | static int bcm_kp_open(struct input_dev *dev) | ||
191 | { | ||
192 | struct bcm_kp *kp = input_get_drvdata(dev); | ||
193 | |||
194 | return bcm_kp_start(kp); | ||
195 | } | ||
196 | |||
197 | static void bcm_kp_close(struct input_dev *dev) | ||
198 | { | ||
199 | struct bcm_kp *kp = input_get_drvdata(dev); | ||
200 | |||
201 | bcm_kp_stop(kp); | ||
202 | } | ||
203 | |||
204 | static int bcm_kp_matrix_key_parse_dt(struct bcm_kp *kp) | ||
205 | { | ||
206 | struct device *dev = kp->input_dev->dev.parent; | ||
207 | struct device_node *np = dev->of_node; | ||
208 | int error; | ||
209 | unsigned int dt_val; | ||
210 | unsigned int i; | ||
211 | unsigned int num_rows, col_mask, rows_set; | ||
212 | |||
213 | /* Initialize the KPCR Keypad Configuration Register */ | ||
214 | kp->kpcr = KPCR_STATUSFILTERENABLE | KPCR_COLFILTERENABLE; | ||
215 | |||
216 | error = matrix_keypad_parse_of_params(dev, &kp->n_rows, &kp->n_cols); | ||
217 | if (error) { | ||
218 | dev_err(dev, "failed to parse kp params\n"); | ||
219 | return error; | ||
220 | } | ||
221 | |||
222 | /* Set row width for the ASIC block. */ | ||
223 | kp->kpcr |= (kp->n_rows - 1) << KPCR_ROWWIDTH_SHIFT; | ||
224 | |||
225 | /* Set column width for the ASIC block. */ | ||
226 | kp->kpcr |= (kp->n_cols - 1) << KPCR_COLUMNWIDTH_SHIFT; | ||
227 | |||
228 | /* Configure the IMR registers */ | ||
229 | |||
230 | /* | ||
231 | * IMR registers contain interrupt enable bits for 8x8 matrix | ||
232 | * IMR0 register format: <row3> <row2> <row1> <row0> | ||
233 | * IMR1 register format: <row7> <row6> <row5> <row4> | ||
234 | */ | ||
235 | col_mask = (1 << (kp->n_cols)) - 1; | ||
236 | num_rows = kp->n_rows; | ||
237 | |||
238 | /* Set column bits in rows 0 to 3 in IMR0 */ | ||
239 | kp->imr0_val = col_mask; | ||
240 | |||
241 | rows_set = 1; | ||
242 | while (--num_rows && rows_set++ < 4) | ||
243 | kp->imr0_val |= kp->imr0_val << MAX_COLS; | ||
244 | |||
245 | /* Set column bits in rows 4 to 7 in IMR1 */ | ||
246 | kp->imr1_val = 0; | ||
247 | if (num_rows) { | ||
248 | kp->imr1_val = col_mask; | ||
249 | while (--num_rows) | ||
250 | kp->imr1_val |= kp->imr1_val << MAX_COLS; | ||
251 | } | ||
252 | |||
253 | /* Initialize the KPEMR Keypress Edge Mode Registers */ | ||
254 | /* Trigger on both edges */ | ||
255 | kp->kpemr = 0; | ||
256 | for (i = 0; i <= 30; i += 2) | ||
257 | kp->kpemr |= (KPEMR_EDGETYPE_BOTH << i); | ||
258 | |||
259 | /* | ||
260 | * Obtain the Status filter debounce value and verify against the | ||
261 | * possible values specified in the DT binding. | ||
262 | */ | ||
263 | of_property_read_u32(np, "status-debounce-filter-period", &dt_val); | ||
264 | |||
265 | if (dt_val > KPCR_STATUSFILTERTYPE_MAX) { | ||
266 | dev_err(dev, "Invalid Status filter debounce value %d\n", | ||
267 | dt_val); | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | |||
271 | kp->kpcr |= dt_val << KPCR_STATUSFILTERTYPE_SHIFT; | ||
272 | |||
273 | /* | ||
274 | * Obtain the Column filter debounce value and verify against the | ||
275 | * possible values specified in the DT binding. | ||
276 | */ | ||
277 | of_property_read_u32(np, "col-debounce-filter-period", &dt_val); | ||
278 | |||
279 | if (dt_val > KPCR_COLFILTERTYPE_MAX) { | ||
280 | dev_err(dev, "Invalid Column filter debounce value %d\n", | ||
281 | dt_val); | ||
282 | return -EINVAL; | ||
283 | } | ||
284 | |||
285 | kp->kpcr |= dt_val << KPCR_COLFILTERTYPE_SHIFT; | ||
286 | |||
287 | /* | ||
288 | * Determine between the row and column, | ||
289 | * which should be configured as output. | ||
290 | */ | ||
291 | if (of_property_read_bool(np, "row-output-enabled")) { | ||
292 | /* | ||
293 | * Set RowOContrl or ColumnOContrl in KPIOR | ||
294 | * to the number of pins to drive as outputs | ||
295 | */ | ||
296 | kp->kpior = ((1 << kp->n_rows) - 1) << | ||
297 | KPIOR_ROWOCONTRL_SHIFT; | ||
298 | } else { | ||
299 | kp->kpior = ((1 << kp->n_cols) - 1) << | ||
300 | KPIOR_COLUMNOCONTRL_SHIFT; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Determine if the scan pull up needs to be enabled | ||
305 | */ | ||
306 | if (of_property_read_bool(np, "pull-up-enabled")) | ||
307 | kp->kpcr |= KPCR_MODE; | ||
308 | |||
309 | dev_dbg(dev, "n_rows=%d n_col=%d kpcr=%x kpior=%x kpemr=%x\n", | ||
310 | kp->n_rows, kp->n_cols, | ||
311 | kp->kpcr, kp->kpior, kp->kpemr); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | |||
317 | static int bcm_kp_probe(struct platform_device *pdev) | ||
318 | { | ||
319 | struct bcm_kp *kp; | ||
320 | struct input_dev *input_dev; | ||
321 | struct resource *res; | ||
322 | int error; | ||
323 | |||
324 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); | ||
325 | if (!kp) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | input_dev = devm_input_allocate_device(&pdev->dev); | ||
329 | if (!input_dev) { | ||
330 | dev_err(&pdev->dev, "failed to allocate the input device\n"); | ||
331 | return -ENOMEM; | ||
332 | } | ||
333 | |||
334 | __set_bit(EV_KEY, input_dev->evbit); | ||
335 | |||
336 | /* Enable auto repeat feature of Linux input subsystem */ | ||
337 | if (of_property_read_bool(pdev->dev.of_node, "autorepeat")) | ||
338 | __set_bit(EV_REP, input_dev->evbit); | ||
339 | |||
340 | input_dev->name = pdev->name; | ||
341 | input_dev->phys = "keypad/input0"; | ||
342 | input_dev->dev.parent = &pdev->dev; | ||
343 | input_dev->open = bcm_kp_open; | ||
344 | input_dev->close = bcm_kp_close; | ||
345 | |||
346 | input_dev->id.bustype = BUS_HOST; | ||
347 | input_dev->id.vendor = 0x0001; | ||
348 | input_dev->id.product = 0x0001; | ||
349 | input_dev->id.version = 0x0100; | ||
350 | |||
351 | input_set_drvdata(input_dev, kp); | ||
352 | |||
353 | kp->input_dev = input_dev; | ||
354 | |||
355 | platform_set_drvdata(pdev, kp); | ||
356 | |||
357 | error = bcm_kp_matrix_key_parse_dt(kp); | ||
358 | if (error) | ||
359 | return error; | ||
360 | |||
361 | error = matrix_keypad_build_keymap(NULL, NULL, | ||
362 | kp->n_rows, kp->n_cols, | ||
363 | NULL, input_dev); | ||
364 | if (error) { | ||
365 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
366 | return error; | ||
367 | } | ||
368 | |||
369 | /* Get the KEYPAD base address */ | ||
370 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
371 | if (!res) { | ||
372 | dev_err(&pdev->dev, "Missing keypad base address resource\n"); | ||
373 | return -ENODEV; | ||
374 | } | ||
375 | |||
376 | kp->base = devm_ioremap_resource(&pdev->dev, res); | ||
377 | if (IS_ERR(kp->base)) | ||
378 | return PTR_ERR(kp->base); | ||
379 | |||
380 | /* Enable clock */ | ||
381 | kp->clk = devm_clk_get(&pdev->dev, "peri_clk"); | ||
382 | if (IS_ERR(kp->clk)) { | ||
383 | error = PTR_ERR(kp->clk); | ||
384 | if (error != -ENOENT) { | ||
385 | if (error != -EPROBE_DEFER) | ||
386 | dev_err(&pdev->dev, "Failed to get clock\n"); | ||
387 | return error; | ||
388 | } | ||
389 | dev_dbg(&pdev->dev, | ||
390 | "No clock specified. Assuming it's enabled\n"); | ||
391 | kp->clk = NULL; | ||
392 | } else { | ||
393 | unsigned int desired_rate; | ||
394 | long actual_rate; | ||
395 | |||
396 | error = of_property_read_u32(pdev->dev.of_node, | ||
397 | "clock-frequency", &desired_rate); | ||
398 | if (error < 0) | ||
399 | desired_rate = DEFAULT_CLK_HZ; | ||
400 | |||
401 | actual_rate = clk_round_rate(kp->clk, desired_rate); | ||
402 | if (actual_rate <= 0) | ||
403 | return -EINVAL; | ||
404 | |||
405 | error = clk_set_rate(kp->clk, actual_rate); | ||
406 | if (error) | ||
407 | return error; | ||
408 | |||
409 | error = clk_prepare_enable(kp->clk); | ||
410 | if (error) | ||
411 | return error; | ||
412 | } | ||
413 | |||
414 | /* Put the kp into a known sane state */ | ||
415 | bcm_kp_stop(kp); | ||
416 | |||
417 | kp->irq = platform_get_irq(pdev, 0); | ||
418 | if (kp->irq < 0) { | ||
419 | dev_err(&pdev->dev, "no IRQ specified\n"); | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | error = devm_request_threaded_irq(&pdev->dev, kp->irq, | ||
424 | NULL, bcm_kp_isr_thread, | ||
425 | IRQF_ONESHOT, pdev->name, kp); | ||
426 | if (error) { | ||
427 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
428 | return error; | ||
429 | } | ||
430 | |||
431 | error = input_register_device(input_dev); | ||
432 | if (error) { | ||
433 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
434 | return error; | ||
435 | } | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static const struct of_device_id bcm_kp_of_match[] = { | ||
441 | { .compatible = "brcm,bcm-keypad" }, | ||
442 | { }, | ||
443 | }; | ||
444 | MODULE_DEVICE_TABLE(of, bcm_kp_of_match); | ||
445 | |||
446 | static struct platform_driver bcm_kp_device_driver = { | ||
447 | .probe = bcm_kp_probe, | ||
448 | .driver = { | ||
449 | .name = "bcm-keypad", | ||
450 | .of_match_table = of_match_ptr(bcm_kp_of_match), | ||
451 | } | ||
452 | }; | ||
453 | |||
454 | module_platform_driver(bcm_kp_device_driver); | ||
455 | |||
456 | MODULE_AUTHOR("Broadcom Corporation"); | ||
457 | MODULE_DESCRIPTION("BCM Keypad Driver"); | ||
458 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index ffa989f2c785..64b9b59ad4cb 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c | |||
@@ -338,7 +338,7 @@ static int cros_ec_keyb_resume(struct device *dev) | |||
338 | * wake source (e.g. the lid is open and the user might press a key to | 338 | * wake source (e.g. the lid is open and the user might press a key to |
339 | * wake) then the key scan buffer should be preserved. | 339 | * wake) then the key scan buffer should be preserved. |
340 | */ | 340 | */ |
341 | if (ckdev->ec->was_wake_device) | 341 | if (!ckdev->ec->was_wake_device) |
342 | cros_ec_keyb_clear_keyboard(ckdev); | 342 | cros_ec_keyb_clear_keyboard(ckdev); |
343 | 343 | ||
344 | return 0; | 344 | return 0; |
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 90df4df58b07..097d7216d98e 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c | |||
@@ -125,7 +125,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct | |||
125 | device_for_each_child_node(dev, child) { | 125 | device_for_each_child_node(dev, child) { |
126 | struct gpio_desc *desc; | 126 | struct gpio_desc *desc; |
127 | 127 | ||
128 | desc = devm_get_gpiod_from_child(dev, child); | 128 | desc = devm_get_gpiod_from_child(dev, NULL, child); |
129 | if (IS_ERR(desc)) { | 129 | if (IS_ERR(desc)) { |
130 | error = PTR_ERR(desc); | 130 | error = PTR_ERR(desc); |
131 | if (error != -EPROBE_DEFER) | 131 | if (error != -EPROBE_DEFER) |
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c new file mode 100644 index 000000000000..602900d1f937 --- /dev/null +++ b/drivers/input/keyboard/ipaq-micro-keys.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License version 2 as | ||
4 | * published by the Free Software Foundation. | ||
5 | * | ||
6 | * h3600 atmel micro companion support, key subdevice | ||
7 | * based on previous kernel 2.4 version | ||
8 | * Author : Alessandro Gardich <gremlin@gremlin.it> | ||
9 | * Author : Linus Walleij <linus.walleij@linaro.org> | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/sysctl.h> | ||
19 | #include <linux/proc_fs.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/input.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/mfd/ipaq-micro.h> | ||
25 | |||
26 | struct ipaq_micro_keys { | ||
27 | struct ipaq_micro *micro; | ||
28 | struct input_dev *input; | ||
29 | u16 *codes; | ||
30 | }; | ||
31 | |||
32 | static const u16 micro_keycodes[] = { | ||
33 | KEY_RECORD, /* 1: Record button */ | ||
34 | KEY_CALENDAR, /* 2: Calendar */ | ||
35 | KEY_ADDRESSBOOK, /* 3: Contacts (looks like Outlook) */ | ||
36 | KEY_MAIL, /* 4: Envelope (Q on older iPAQs) */ | ||
37 | KEY_HOMEPAGE, /* 5: Start (looks like swoopy arrow) */ | ||
38 | KEY_UP, /* 6: Up */ | ||
39 | KEY_RIGHT, /* 7: Right */ | ||
40 | KEY_LEFT, /* 8: Left */ | ||
41 | KEY_DOWN, /* 9: Down */ | ||
42 | }; | ||
43 | |||
44 | static void micro_key_receive(void *data, int len, unsigned char *msg) | ||
45 | { | ||
46 | struct ipaq_micro_keys *keys = data; | ||
47 | int key, down; | ||
48 | |||
49 | down = 0x80 & msg[0]; | ||
50 | key = 0x7f & msg[0]; | ||
51 | |||
52 | if (key < ARRAY_SIZE(micro_keycodes)) { | ||
53 | input_report_key(keys->input, keys->codes[key], down); | ||
54 | input_sync(keys->input); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static void micro_key_start(struct ipaq_micro_keys *keys) | ||
59 | { | ||
60 | spin_lock(&keys->micro->lock); | ||
61 | keys->micro->key = micro_key_receive; | ||
62 | keys->micro->key_data = keys; | ||
63 | spin_unlock(&keys->micro->lock); | ||
64 | } | ||
65 | |||
66 | static void micro_key_stop(struct ipaq_micro_keys *keys) | ||
67 | { | ||
68 | spin_lock(&keys->micro->lock); | ||
69 | keys->micro->key = NULL; | ||
70 | keys->micro->key_data = NULL; | ||
71 | spin_unlock(&keys->micro->lock); | ||
72 | } | ||
73 | |||
74 | static int micro_key_open(struct input_dev *input) | ||
75 | { | ||
76 | struct ipaq_micro_keys *keys = input_get_drvdata(input); | ||
77 | |||
78 | micro_key_start(keys); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void micro_key_close(struct input_dev *input) | ||
84 | { | ||
85 | struct ipaq_micro_keys *keys = input_get_drvdata(input); | ||
86 | |||
87 | micro_key_stop(keys); | ||
88 | } | ||
89 | |||
90 | static int micro_key_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct ipaq_micro_keys *keys; | ||
93 | int error; | ||
94 | int i; | ||
95 | |||
96 | keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL); | ||
97 | if (!keys) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | keys->micro = dev_get_drvdata(pdev->dev.parent); | ||
101 | |||
102 | keys->input = devm_input_allocate_device(&pdev->dev); | ||
103 | if (!keys->input) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | keys->input->keycodesize = sizeof(micro_keycodes[0]); | ||
107 | keys->input->keycodemax = ARRAY_SIZE(micro_keycodes); | ||
108 | keys->codes = devm_kmemdup(&pdev->dev, micro_keycodes, | ||
109 | keys->input->keycodesize * keys->input->keycodemax, | ||
110 | GFP_KERNEL); | ||
111 | keys->input->keycode = keys->codes; | ||
112 | |||
113 | __set_bit(EV_KEY, keys->input->evbit); | ||
114 | for (i = 0; i < ARRAY_SIZE(micro_keycodes); i++) | ||
115 | __set_bit(micro_keycodes[i], keys->input->keybit); | ||
116 | |||
117 | keys->input->name = "h3600 micro keys"; | ||
118 | keys->input->open = micro_key_open; | ||
119 | keys->input->close = micro_key_close; | ||
120 | input_set_drvdata(keys->input, keys); | ||
121 | |||
122 | error = input_register_device(keys->input); | ||
123 | if (error) | ||
124 | return error; | ||
125 | |||
126 | platform_set_drvdata(pdev, keys); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | static int __maybe_unused micro_key_suspend(struct device *dev) | ||
131 | { | ||
132 | struct ipaq_micro_keys *keys = dev_get_drvdata(dev); | ||
133 | |||
134 | micro_key_stop(keys); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int __maybe_unused micro_key_resume(struct device *dev) | ||
140 | { | ||
141 | struct ipaq_micro_keys *keys = dev_get_drvdata(dev); | ||
142 | struct input_dev *input = keys->input; | ||
143 | |||
144 | mutex_lock(&input->mutex); | ||
145 | |||
146 | if (input->users) | ||
147 | micro_key_start(keys); | ||
148 | |||
149 | mutex_unlock(&input->mutex); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops, | ||
155 | micro_key_suspend, micro_key_resume); | ||
156 | |||
157 | static struct platform_driver micro_key_device_driver = { | ||
158 | .driver = { | ||
159 | .name = "ipaq-micro-keys", | ||
160 | .pm = µ_key_dev_pm_ops, | ||
161 | }, | ||
162 | .probe = micro_key_probe, | ||
163 | }; | ||
164 | module_platform_driver(micro_key_device_driver); | ||
165 | |||
166 | MODULE_LICENSE("GPL"); | ||
167 | MODULE_DESCRIPTION("driver for iPAQ Atmel micro keys"); | ||
168 | MODULE_ALIAS("platform:ipaq-micro-keys"); | ||
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 8ff612d160b0..31c606a4dd31 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -70,6 +70,28 @@ | |||
70 | #define TC3589x_KBD_INT_CLR 0x1 | 70 | #define TC3589x_KBD_INT_CLR 0x1 |
71 | 71 | ||
72 | /** | 72 | /** |
73 | * struct tc35893_keypad_platform_data - platform specific keypad data | ||
74 | * @keymap_data: matrix scan code table for keycodes | ||
75 | * @krow: mask for available rows, value is 0xFF | ||
76 | * @kcol: mask for available columns, value is 0xFF | ||
77 | * @debounce_period: platform specific debounce time | ||
78 | * @settle_time: platform specific settle down time | ||
79 | * @irqtype: type of interrupt, falling or rising edge | ||
80 | * @enable_wakeup: specifies if keypad event can wake up system from sleep | ||
81 | * @no_autorepeat: flag for auto repetition | ||
82 | */ | ||
83 | struct tc3589x_keypad_platform_data { | ||
84 | const struct matrix_keymap_data *keymap_data; | ||
85 | u8 krow; | ||
86 | u8 kcol; | ||
87 | u8 debounce_period; | ||
88 | u8 settle_time; | ||
89 | unsigned long irqtype; | ||
90 | bool enable_wakeup; | ||
91 | bool no_autorepeat; | ||
92 | }; | ||
93 | |||
94 | /** | ||
73 | * struct tc_keypad - data structure used by keypad driver | 95 | * struct tc_keypad - data structure used by keypad driver |
74 | * @tc3589x: pointer to tc35893 | 96 | * @tc3589x: pointer to tc35893 |
75 | * @input: pointer to input device object | 97 | * @input: pointer to input device object |
@@ -296,7 +318,6 @@ static void tc3589x_keypad_close(struct input_dev *input) | |||
296 | tc3589x_keypad_disable(keypad); | 318 | tc3589x_keypad_disable(keypad); |
297 | } | 319 | } |
298 | 320 | ||
299 | #ifdef CONFIG_OF | ||
300 | static const struct tc3589x_keypad_platform_data * | 321 | static const struct tc3589x_keypad_platform_data * |
301 | tc3589x_keypad_of_probe(struct device *dev) | 322 | tc3589x_keypad_of_probe(struct device *dev) |
302 | { | 323 | { |
@@ -346,14 +367,6 @@ tc3589x_keypad_of_probe(struct device *dev) | |||
346 | 367 | ||
347 | return plat; | 368 | return plat; |
348 | } | 369 | } |
349 | #else | ||
350 | static inline const struct tc3589x_keypad_platform_data * | ||
351 | tc3589x_keypad_of_probe(struct device *dev) | ||
352 | { | ||
353 | return ERR_PTR(-ENODEV); | ||
354 | } | ||
355 | #endif | ||
356 | |||
357 | 370 | ||
358 | static int tc3589x_keypad_probe(struct platform_device *pdev) | 371 | static int tc3589x_keypad_probe(struct platform_device *pdev) |
359 | { | 372 | { |
@@ -363,13 +376,10 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) | |||
363 | const struct tc3589x_keypad_platform_data *plat; | 376 | const struct tc3589x_keypad_platform_data *plat; |
364 | int error, irq; | 377 | int error, irq; |
365 | 378 | ||
366 | plat = tc3589x->pdata->keypad; | 379 | plat = tc3589x_keypad_of_probe(&pdev->dev); |
367 | if (!plat) { | 380 | if (IS_ERR(plat)) { |
368 | plat = tc3589x_keypad_of_probe(&pdev->dev); | 381 | dev_err(&pdev->dev, "invalid keypad platform data\n"); |
369 | if (IS_ERR(plat)) { | 382 | return PTR_ERR(plat); |
370 | dev_err(&pdev->dev, "invalid keypad platform data\n"); | ||
371 | return PTR_ERR(plat); | ||
372 | } | ||
373 | } | 383 | } |
374 | 384 | ||
375 | irq = platform_get_irq(pdev, 0); | 385 | irq = platform_get_irq(pdev, 0); |
@@ -411,9 +421,9 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) | |||
411 | 421 | ||
412 | input_set_drvdata(input, keypad); | 422 | input_set_drvdata(input, keypad); |
413 | 423 | ||
414 | error = request_threaded_irq(irq, NULL, | 424 | error = request_threaded_irq(irq, NULL, tc3589x_keypad_irq, |
415 | tc3589x_keypad_irq, plat->irqtype, | 425 | plat->irqtype | IRQF_ONESHOT, |
416 | "tc3589x-keypad", keypad); | 426 | "tc3589x-keypad", keypad); |
417 | if (error < 0) { | 427 | if (error < 0) { |
418 | dev_err(&pdev->dev, | 428 | dev_err(&pdev->dev, |
419 | "Could not allocate irq %d,error %d\n", | 429 | "Could not allocate irq %d,error %d\n", |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6deb8dae3205..4436ab1b9735 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -115,6 +115,18 @@ config INPUT_PCSPKR | |||
115 | To compile this driver as a module, choose M here: the | 115 | To compile this driver as a module, choose M here: the |
116 | module will be called pcspkr. | 116 | module will be called pcspkr. |
117 | 117 | ||
118 | config INPUT_PM8941_PWRKEY | ||
119 | tristate "Qualcomm PM8941 power key support" | ||
120 | depends on MFD_SPMI_PMIC | ||
121 | help | ||
122 | Say Y here if you want support for the power key usually found | ||
123 | on boards using a Qualcomm PM8941 compatible PMIC. | ||
124 | |||
125 | If unsure, say Y. | ||
126 | |||
127 | To compile this driver as a module, choose M here: the module | ||
128 | will be called pm8941-pwrkey. | ||
129 | |||
118 | config INPUT_PM8XXX_VIBRATOR | 130 | config INPUT_PM8XXX_VIBRATOR |
119 | tristate "Qualcomm PM8XXX vibrator support" | 131 | tristate "Qualcomm PM8XXX vibrator support" |
120 | depends on MFD_PM8XXX | 132 | depends on MFD_PM8XXX |
@@ -165,6 +177,18 @@ config INPUT_MAX77693_HAPTIC | |||
165 | To compile this driver as module, choose M here: the | 177 | To compile this driver as module, choose M here: the |
166 | module will be called max77693-haptic. | 178 | module will be called max77693-haptic. |
167 | 179 | ||
180 | config INPUT_MAX77843_HAPTIC | ||
181 | tristate "MAXIM MAX77843 haptic controller support" | ||
182 | depends on MFD_MAX77843 && REGULATOR | ||
183 | select INPUT_FF_MEMLESS | ||
184 | help | ||
185 | This option enables support for the haptic controller on | ||
186 | MAXIM MAX77843 chip. The driver supports ff-memless interface | ||
187 | from input framework. | ||
188 | |||
189 | To compile this driver as module, choose M here: the | ||
190 | module will be called max77843-haptic. | ||
191 | |||
168 | config INPUT_MAX8925_ONKEY | 192 | config INPUT_MAX8925_ONKEY |
169 | tristate "MAX8925 ONKEY support" | 193 | tristate "MAX8925 ONKEY support" |
170 | depends on MFD_MAX8925 | 194 | depends on MFD_MAX8925 |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 403a1a54a76c..78ba4c1b8532 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | |||
39 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o | 39 | obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o |
40 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 40 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
41 | obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o | 41 | obj-$(CONFIG_INPUT_MAX77693_HAPTIC) += max77693-haptic.o |
42 | obj-$(CONFIG_INPUT_MAX77843_HAPTIC) += max77843-haptic.o | ||
42 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o | 43 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o |
43 | obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o | 44 | obj-$(CONFIG_INPUT_MAX8997_HAPTIC) += max8997_haptic.o |
44 | obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o | 45 | obj-$(CONFIG_INPUT_MC13783_PWRBUTTON) += mc13783-pwrbutton.o |
@@ -49,6 +50,7 @@ obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o | |||
49 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 50 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
50 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o | 51 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o |
51 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 52 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
53 | obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o | ||
52 | obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o | 54 | obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o |
53 | obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o | 55 | obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o |
54 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 56 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
diff --git a/drivers/input/misc/max77843-haptic.c b/drivers/input/misc/max77843-haptic.c new file mode 100644 index 000000000000..dccbb465a055 --- /dev/null +++ b/drivers/input/misc/max77843-haptic.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * MAXIM MAX77693 Haptic device driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Samsung Electronics | ||
5 | * Author: Jaewon Kim <jaewon02.kim@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/err.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/mfd/max77843-private.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/pwm.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #define MAX_MAGNITUDE_SHIFT 16 | ||
27 | |||
28 | enum max77843_haptic_motor_type { | ||
29 | MAX77843_HAPTIC_ERM = 0, | ||
30 | MAX77843_HAPTIC_LRA, | ||
31 | }; | ||
32 | |||
33 | enum max77843_haptic_pwm_divisor { | ||
34 | MAX77843_HAPTIC_PWM_DIVISOR_32 = 0, | ||
35 | MAX77843_HAPTIC_PWM_DIVISOR_64, | ||
36 | MAX77843_HAPTIC_PWM_DIVISOR_128, | ||
37 | MAX77843_HAPTIC_PWM_DIVISOR_256, | ||
38 | }; | ||
39 | |||
40 | struct max77843_haptic { | ||
41 | struct regmap *regmap_haptic; | ||
42 | struct device *dev; | ||
43 | struct input_dev *input_dev; | ||
44 | struct pwm_device *pwm_dev; | ||
45 | struct regulator *motor_reg; | ||
46 | struct work_struct work; | ||
47 | struct mutex mutex; | ||
48 | |||
49 | unsigned int magnitude; | ||
50 | unsigned int pwm_duty; | ||
51 | |||
52 | bool active; | ||
53 | bool suspended; | ||
54 | |||
55 | enum max77843_haptic_motor_type type; | ||
56 | enum max77843_haptic_pwm_divisor pwm_divisor; | ||
57 | }; | ||
58 | |||
59 | static int max77843_haptic_set_duty_cycle(struct max77843_haptic *haptic) | ||
60 | { | ||
61 | int delta = (haptic->pwm_dev->period + haptic->pwm_duty) / 2; | ||
62 | int error; | ||
63 | |||
64 | error = pwm_config(haptic->pwm_dev, delta, haptic->pwm_dev->period); | ||
65 | if (error) { | ||
66 | dev_err(haptic->dev, "failed to configure pwm: %d\n", error); | ||
67 | return error; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int max77843_haptic_bias(struct max77843_haptic *haptic, bool on) | ||
74 | { | ||
75 | int error; | ||
76 | |||
77 | error = regmap_update_bits(haptic->regmap_haptic, | ||
78 | MAX77843_SYS_REG_MAINCTRL1, | ||
79 | MAX77843_MAINCTRL1_BIASEN_MASK, | ||
80 | on << MAINCTRL1_BIASEN_SHIFT); | ||
81 | if (error) { | ||
82 | dev_err(haptic->dev, "failed to %s bias: %d\n", | ||
83 | on ? "enable" : "disable", error); | ||
84 | return error; | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int max77843_haptic_config(struct max77843_haptic *haptic, bool enable) | ||
91 | { | ||
92 | unsigned int value; | ||
93 | int error; | ||
94 | |||
95 | value = (haptic->type << MCONFIG_MODE_SHIFT) | | ||
96 | (enable << MCONFIG_MEN_SHIFT) | | ||
97 | (haptic->pwm_divisor << MCONFIG_PDIV_SHIFT); | ||
98 | |||
99 | error = regmap_write(haptic->regmap_haptic, | ||
100 | MAX77843_HAP_REG_MCONFIG, value); | ||
101 | if (error) { | ||
102 | dev_err(haptic->dev, | ||
103 | "failed to update haptic config: %d\n", error); | ||
104 | return error; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int max77843_haptic_enable(struct max77843_haptic *haptic) | ||
111 | { | ||
112 | int error; | ||
113 | |||
114 | if (haptic->active) | ||
115 | return 0; | ||
116 | |||
117 | error = pwm_enable(haptic->pwm_dev); | ||
118 | if (error) { | ||
119 | dev_err(haptic->dev, | ||
120 | "failed to enable pwm device: %d\n", error); | ||
121 | return error; | ||
122 | } | ||
123 | |||
124 | error = max77843_haptic_config(haptic, true); | ||
125 | if (error) | ||
126 | goto err_config; | ||
127 | |||
128 | haptic->active = true; | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err_config: | ||
133 | pwm_disable(haptic->pwm_dev); | ||
134 | |||
135 | return error; | ||
136 | } | ||
137 | |||
138 | static int max77843_haptic_disable(struct max77843_haptic *haptic) | ||
139 | { | ||
140 | int error; | ||
141 | |||
142 | if (!haptic->active) | ||
143 | return 0; | ||
144 | |||
145 | error = max77843_haptic_config(haptic, false); | ||
146 | if (error) | ||
147 | return error; | ||
148 | |||
149 | pwm_disable(haptic->pwm_dev); | ||
150 | |||
151 | haptic->active = false; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static void max77843_haptic_play_work(struct work_struct *work) | ||
157 | { | ||
158 | struct max77843_haptic *haptic = | ||
159 | container_of(work, struct max77843_haptic, work); | ||
160 | int error; | ||
161 | |||
162 | mutex_lock(&haptic->mutex); | ||
163 | |||
164 | if (haptic->suspended) | ||
165 | goto out_unlock; | ||
166 | |||
167 | if (haptic->magnitude) { | ||
168 | error = max77843_haptic_set_duty_cycle(haptic); | ||
169 | if (error) { | ||
170 | dev_err(haptic->dev, | ||
171 | "failed to set duty cycle: %d\n", error); | ||
172 | goto out_unlock; | ||
173 | } | ||
174 | |||
175 | error = max77843_haptic_enable(haptic); | ||
176 | if (error) | ||
177 | dev_err(haptic->dev, | ||
178 | "cannot enable haptic: %d\n", error); | ||
179 | } else { | ||
180 | error = max77843_haptic_disable(haptic); | ||
181 | if (error) | ||
182 | dev_err(haptic->dev, | ||
183 | "cannot disable haptic: %d\n", error); | ||
184 | } | ||
185 | |||
186 | out_unlock: | ||
187 | mutex_unlock(&haptic->mutex); | ||
188 | } | ||
189 | |||
190 | static int max77843_haptic_play_effect(struct input_dev *dev, void *data, | ||
191 | struct ff_effect *effect) | ||
192 | { | ||
193 | struct max77843_haptic *haptic = input_get_drvdata(dev); | ||
194 | u64 period_mag_multi; | ||
195 | |||
196 | haptic->magnitude = effect->u.rumble.strong_magnitude; | ||
197 | if (!haptic->magnitude) | ||
198 | haptic->magnitude = effect->u.rumble.weak_magnitude; | ||
199 | |||
200 | period_mag_multi = (u64)haptic->pwm_dev->period * haptic->magnitude; | ||
201 | haptic->pwm_duty = (unsigned int)(period_mag_multi >> | ||
202 | MAX_MAGNITUDE_SHIFT); | ||
203 | |||
204 | schedule_work(&haptic->work); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int max77843_haptic_open(struct input_dev *dev) | ||
210 | { | ||
211 | struct max77843_haptic *haptic = input_get_drvdata(dev); | ||
212 | int error; | ||
213 | |||
214 | error = max77843_haptic_bias(haptic, true); | ||
215 | if (error) | ||
216 | return error; | ||
217 | |||
218 | error = regulator_enable(haptic->motor_reg); | ||
219 | if (error) { | ||
220 | dev_err(haptic->dev, | ||
221 | "failed to enable regulator: %d\n", error); | ||
222 | return error; | ||
223 | } | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void max77843_haptic_close(struct input_dev *dev) | ||
229 | { | ||
230 | struct max77843_haptic *haptic = input_get_drvdata(dev); | ||
231 | int error; | ||
232 | |||
233 | cancel_work_sync(&haptic->work); | ||
234 | max77843_haptic_disable(haptic); | ||
235 | |||
236 | error = regulator_disable(haptic->motor_reg); | ||
237 | if (error) | ||
238 | dev_err(haptic->dev, | ||
239 | "failed to disable regulator: %d\n", error); | ||
240 | |||
241 | max77843_haptic_bias(haptic, false); | ||
242 | } | ||
243 | |||
244 | static int max77843_haptic_probe(struct platform_device *pdev) | ||
245 | { | ||
246 | struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); | ||
247 | struct max77843_haptic *haptic; | ||
248 | int error; | ||
249 | |||
250 | haptic = devm_kzalloc(&pdev->dev, sizeof(*haptic), GFP_KERNEL); | ||
251 | if (!haptic) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | haptic->regmap_haptic = max77843->regmap; | ||
255 | haptic->dev = &pdev->dev; | ||
256 | haptic->type = MAX77843_HAPTIC_LRA; | ||
257 | haptic->pwm_divisor = MAX77843_HAPTIC_PWM_DIVISOR_128; | ||
258 | |||
259 | INIT_WORK(&haptic->work, max77843_haptic_play_work); | ||
260 | mutex_init(&haptic->mutex); | ||
261 | |||
262 | haptic->pwm_dev = devm_pwm_get(&pdev->dev, NULL); | ||
263 | if (IS_ERR(haptic->pwm_dev)) { | ||
264 | dev_err(&pdev->dev, "failed to get pwm device\n"); | ||
265 | return PTR_ERR(haptic->pwm_dev); | ||
266 | } | ||
267 | |||
268 | haptic->motor_reg = devm_regulator_get_exclusive(&pdev->dev, "haptic"); | ||
269 | if (IS_ERR(haptic->motor_reg)) { | ||
270 | dev_err(&pdev->dev, "failed to get regulator\n"); | ||
271 | return PTR_ERR(haptic->motor_reg); | ||
272 | } | ||
273 | |||
274 | haptic->input_dev = devm_input_allocate_device(&pdev->dev); | ||
275 | if (!haptic->input_dev) { | ||
276 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
277 | return -ENOMEM; | ||
278 | } | ||
279 | |||
280 | haptic->input_dev->name = "max77843-haptic"; | ||
281 | haptic->input_dev->id.version = 1; | ||
282 | haptic->input_dev->dev.parent = &pdev->dev; | ||
283 | haptic->input_dev->open = max77843_haptic_open; | ||
284 | haptic->input_dev->close = max77843_haptic_close; | ||
285 | input_set_drvdata(haptic->input_dev, haptic); | ||
286 | input_set_capability(haptic->input_dev, EV_FF, FF_RUMBLE); | ||
287 | |||
288 | error = input_ff_create_memless(haptic->input_dev, NULL, | ||
289 | max77843_haptic_play_effect); | ||
290 | if (error) { | ||
291 | dev_err(&pdev->dev, "failed to create force-feedback\n"); | ||
292 | return error; | ||
293 | } | ||
294 | |||
295 | error = input_register_device(haptic->input_dev); | ||
296 | if (error) { | ||
297 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
298 | return error; | ||
299 | } | ||
300 | |||
301 | platform_set_drvdata(pdev, haptic); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int __maybe_unused max77843_haptic_suspend(struct device *dev) | ||
307 | { | ||
308 | struct platform_device *pdev = to_platform_device(dev); | ||
309 | struct max77843_haptic *haptic = platform_get_drvdata(pdev); | ||
310 | int error; | ||
311 | |||
312 | error = mutex_lock_interruptible(&haptic->mutex); | ||
313 | if (error) | ||
314 | return error; | ||
315 | |||
316 | max77843_haptic_disable(haptic); | ||
317 | |||
318 | haptic->suspended = true; | ||
319 | |||
320 | mutex_unlock(&haptic->mutex); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int __maybe_unused max77843_haptic_resume(struct device *dev) | ||
326 | { | ||
327 | struct platform_device *pdev = to_platform_device(dev); | ||
328 | struct max77843_haptic *haptic = platform_get_drvdata(pdev); | ||
329 | unsigned int magnitude; | ||
330 | |||
331 | mutex_lock(&haptic->mutex); | ||
332 | |||
333 | haptic->suspended = false; | ||
334 | |||
335 | magnitude = ACCESS_ONCE(haptic->magnitude); | ||
336 | if (magnitude) | ||
337 | max77843_haptic_enable(haptic); | ||
338 | |||
339 | mutex_unlock(&haptic->mutex); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static SIMPLE_DEV_PM_OPS(max77843_haptic_pm_ops, | ||
345 | max77843_haptic_suspend, max77843_haptic_resume); | ||
346 | |||
347 | static struct platform_driver max77843_haptic_driver = { | ||
348 | .driver = { | ||
349 | .name = "max77843-haptic", | ||
350 | .pm = &max77843_haptic_pm_ops, | ||
351 | }, | ||
352 | .probe = max77843_haptic_probe, | ||
353 | }; | ||
354 | module_platform_driver(max77843_haptic_driver); | ||
355 | |||
356 | MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); | ||
357 | MODULE_DESCRIPTION("MAXIM MAX77843 Haptic driver"); | ||
358 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 59d4dcddf6de..19c73574458e 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c | |||
@@ -174,12 +174,13 @@ static int mma8450_probe(struct i2c_client *c, | |||
174 | struct mma8450 *m; | 174 | struct mma8450 *m; |
175 | int err; | 175 | int err; |
176 | 176 | ||
177 | m = kzalloc(sizeof(struct mma8450), GFP_KERNEL); | 177 | m = devm_kzalloc(&c->dev, sizeof(*m), GFP_KERNEL); |
178 | idev = input_allocate_polled_device(); | 178 | if (!m) |
179 | if (!m || !idev) { | 179 | return -ENOMEM; |
180 | err = -ENOMEM; | 180 | |
181 | goto err_free_mem; | 181 | idev = devm_input_allocate_polled_device(&c->dev); |
182 | } | 182 | if (!idev) |
183 | return -ENOMEM; | ||
183 | 184 | ||
184 | m->client = c; | 185 | m->client = c; |
185 | m->idev = idev; | 186 | m->idev = idev; |
@@ -201,29 +202,12 @@ static int mma8450_probe(struct i2c_client *c, | |||
201 | err = input_register_polled_device(idev); | 202 | err = input_register_polled_device(idev); |
202 | if (err) { | 203 | if (err) { |
203 | dev_err(&c->dev, "failed to register polled input device\n"); | 204 | dev_err(&c->dev, "failed to register polled input device\n"); |
204 | goto err_free_mem; | 205 | return err; |
205 | } | 206 | } |
206 | 207 | ||
207 | i2c_set_clientdata(c, m); | 208 | i2c_set_clientdata(c, m); |
208 | 209 | ||
209 | return 0; | 210 | return 0; |
210 | |||
211 | err_free_mem: | ||
212 | input_free_polled_device(idev); | ||
213 | kfree(m); | ||
214 | return err; | ||
215 | } | ||
216 | |||
217 | static int mma8450_remove(struct i2c_client *c) | ||
218 | { | ||
219 | struct mma8450 *m = i2c_get_clientdata(c); | ||
220 | struct input_polled_dev *idev = m->idev; | ||
221 | |||
222 | input_unregister_polled_device(idev); | ||
223 | input_free_polled_device(idev); | ||
224 | kfree(m); | ||
225 | |||
226 | return 0; | ||
227 | } | 211 | } |
228 | 212 | ||
229 | static const struct i2c_device_id mma8450_id[] = { | 213 | static const struct i2c_device_id mma8450_id[] = { |
@@ -241,11 +225,9 @@ MODULE_DEVICE_TABLE(of, mma8450_dt_ids); | |||
241 | static struct i2c_driver mma8450_driver = { | 225 | static struct i2c_driver mma8450_driver = { |
242 | .driver = { | 226 | .driver = { |
243 | .name = MMA8450_DRV_NAME, | 227 | .name = MMA8450_DRV_NAME, |
244 | .owner = THIS_MODULE, | ||
245 | .of_match_table = mma8450_dt_ids, | 228 | .of_match_table = mma8450_dt_ids, |
246 | }, | 229 | }, |
247 | .probe = mma8450_probe, | 230 | .probe = mma8450_probe, |
248 | .remove = mma8450_remove, | ||
249 | .id_table = mma8450_id, | 231 | .id_table = mma8450_id, |
250 | }; | 232 | }; |
251 | 233 | ||
diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c index 1f9b5ee92746..1e1baed63929 100644 --- a/drivers/input/misc/palmas-pwrbutton.c +++ b/drivers/input/misc/palmas-pwrbutton.c | |||
@@ -304,7 +304,7 @@ static SIMPLE_DEV_PM_OPS(palmas_pwron_pm, | |||
304 | palmas_pwron_suspend, palmas_pwron_resume); | 304 | palmas_pwron_suspend, palmas_pwron_resume); |
305 | 305 | ||
306 | #ifdef CONFIG_OF | 306 | #ifdef CONFIG_OF |
307 | static struct of_device_id of_palmas_pwr_match[] = { | 307 | static const struct of_device_id of_palmas_pwr_match[] = { |
308 | { .compatible = "ti,palmas-pwrbutton" }, | 308 | { .compatible = "ti,palmas-pwrbutton" }, |
309 | { }, | 309 | { }, |
310 | }; | 310 | }; |
diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c new file mode 100644 index 000000000000..867db8a91372 --- /dev/null +++ b/drivers/input/misc/pm8941-pwrkey.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. | ||
3 | * Copyright (c) 2014, Sony Mobile Communications Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 and | ||
7 | * only version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/log2.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/reboot.h> | ||
25 | #include <linux/regmap.h> | ||
26 | |||
27 | #define PON_REV2 0x01 | ||
28 | |||
29 | #define PON_RT_STS 0x10 | ||
30 | #define PON_KPDPWR_N_SET BIT(0) | ||
31 | |||
32 | #define PON_PS_HOLD_RST_CTL 0x5a | ||
33 | #define PON_PS_HOLD_RST_CTL2 0x5b | ||
34 | #define PON_PS_HOLD_ENABLE BIT(7) | ||
35 | #define PON_PS_HOLD_TYPE_MASK 0x0f | ||
36 | #define PON_PS_HOLD_TYPE_SHUTDOWN 4 | ||
37 | #define PON_PS_HOLD_TYPE_HARD_RESET 7 | ||
38 | |||
39 | #define PON_PULL_CTL 0x70 | ||
40 | #define PON_KPDPWR_PULL_UP BIT(1) | ||
41 | |||
42 | #define PON_DBC_CTL 0x71 | ||
43 | #define PON_DBC_DELAY_MASK 0x7 | ||
44 | |||
45 | |||
46 | struct pm8941_pwrkey { | ||
47 | struct device *dev; | ||
48 | int irq; | ||
49 | u32 baseaddr; | ||
50 | struct regmap *regmap; | ||
51 | struct input_dev *input; | ||
52 | |||
53 | unsigned int revision; | ||
54 | struct notifier_block reboot_notifier; | ||
55 | }; | ||
56 | |||
57 | static int pm8941_reboot_notify(struct notifier_block *nb, | ||
58 | unsigned long code, void *unused) | ||
59 | { | ||
60 | struct pm8941_pwrkey *pwrkey = container_of(nb, struct pm8941_pwrkey, | ||
61 | reboot_notifier); | ||
62 | unsigned int enable_reg; | ||
63 | unsigned int reset_type; | ||
64 | int error; | ||
65 | |||
66 | /* PMICs with revision 0 have the enable bit in same register as ctrl */ | ||
67 | if (pwrkey->revision == 0) | ||
68 | enable_reg = PON_PS_HOLD_RST_CTL; | ||
69 | else | ||
70 | enable_reg = PON_PS_HOLD_RST_CTL2; | ||
71 | |||
72 | error = regmap_update_bits(pwrkey->regmap, | ||
73 | pwrkey->baseaddr + enable_reg, | ||
74 | PON_PS_HOLD_ENABLE, | ||
75 | 0); | ||
76 | if (error) | ||
77 | dev_err(pwrkey->dev, | ||
78 | "unable to clear ps hold reset enable: %d\n", | ||
79 | error); | ||
80 | |||
81 | /* | ||
82 | * Updates of PON_PS_HOLD_ENABLE requires 3 sleep cycles between | ||
83 | * writes. | ||
84 | */ | ||
85 | usleep_range(100, 1000); | ||
86 | |||
87 | switch (code) { | ||
88 | case SYS_HALT: | ||
89 | case SYS_POWER_OFF: | ||
90 | reset_type = PON_PS_HOLD_TYPE_SHUTDOWN; | ||
91 | break; | ||
92 | case SYS_RESTART: | ||
93 | default: | ||
94 | reset_type = PON_PS_HOLD_TYPE_HARD_RESET; | ||
95 | break; | ||
96 | }; | ||
97 | |||
98 | error = regmap_update_bits(pwrkey->regmap, | ||
99 | pwrkey->baseaddr + PON_PS_HOLD_RST_CTL, | ||
100 | PON_PS_HOLD_TYPE_MASK, | ||
101 | reset_type); | ||
102 | if (error) | ||
103 | dev_err(pwrkey->dev, "unable to set ps hold reset type: %d\n", | ||
104 | error); | ||
105 | |||
106 | error = regmap_update_bits(pwrkey->regmap, | ||
107 | pwrkey->baseaddr + enable_reg, | ||
108 | PON_PS_HOLD_ENABLE, | ||
109 | PON_PS_HOLD_ENABLE); | ||
110 | if (error) | ||
111 | dev_err(pwrkey->dev, "unable to re-set enable: %d\n", error); | ||
112 | |||
113 | return NOTIFY_DONE; | ||
114 | } | ||
115 | |||
116 | static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) | ||
117 | { | ||
118 | struct pm8941_pwrkey *pwrkey = _data; | ||
119 | unsigned int sts; | ||
120 | int error; | ||
121 | |||
122 | error = regmap_read(pwrkey->regmap, | ||
123 | pwrkey->baseaddr + PON_RT_STS, &sts); | ||
124 | if (error) | ||
125 | return IRQ_HANDLED; | ||
126 | |||
127 | input_report_key(pwrkey->input, KEY_POWER, !!(sts & PON_KPDPWR_N_SET)); | ||
128 | input_sync(pwrkey->input); | ||
129 | |||
130 | return IRQ_HANDLED; | ||
131 | } | ||
132 | |||
133 | static int __maybe_unused pm8941_pwrkey_suspend(struct device *dev) | ||
134 | { | ||
135 | struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev); | ||
136 | |||
137 | if (device_may_wakeup(dev)) | ||
138 | enable_irq_wake(pwrkey->irq); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int __maybe_unused pm8941_pwrkey_resume(struct device *dev) | ||
144 | { | ||
145 | struct pm8941_pwrkey *pwrkey = dev_get_drvdata(dev); | ||
146 | |||
147 | if (device_may_wakeup(dev)) | ||
148 | disable_irq_wake(pwrkey->irq); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static SIMPLE_DEV_PM_OPS(pm8941_pwr_key_pm_ops, | ||
154 | pm8941_pwrkey_suspend, pm8941_pwrkey_resume); | ||
155 | |||
156 | static int pm8941_pwrkey_probe(struct platform_device *pdev) | ||
157 | { | ||
158 | struct pm8941_pwrkey *pwrkey; | ||
159 | bool pull_up; | ||
160 | u32 req_delay; | ||
161 | int error; | ||
162 | |||
163 | if (of_property_read_u32(pdev->dev.of_node, "debounce", &req_delay)) | ||
164 | req_delay = 15625; | ||
165 | |||
166 | if (req_delay > 2000000 || req_delay == 0) { | ||
167 | dev_err(&pdev->dev, "invalid debounce time: %u\n", req_delay); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | pull_up = of_property_read_bool(pdev->dev.of_node, "bias-pull-up"); | ||
172 | |||
173 | pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL); | ||
174 | if (!pwrkey) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | pwrkey->dev = &pdev->dev; | ||
178 | |||
179 | pwrkey->regmap = dev_get_regmap(pdev->dev.parent, NULL); | ||
180 | if (!pwrkey->regmap) { | ||
181 | dev_err(&pdev->dev, "failed to locate regmap\n"); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
185 | pwrkey->irq = platform_get_irq(pdev, 0); | ||
186 | if (pwrkey->irq < 0) { | ||
187 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
188 | return pwrkey->irq; | ||
189 | } | ||
190 | |||
191 | error = of_property_read_u32(pdev->dev.of_node, "reg", | ||
192 | &pwrkey->baseaddr); | ||
193 | if (error) | ||
194 | return error; | ||
195 | |||
196 | error = regmap_read(pwrkey->regmap, pwrkey->baseaddr + PON_REV2, | ||
197 | &pwrkey->revision); | ||
198 | if (error) { | ||
199 | dev_err(&pdev->dev, "failed to set debounce: %d\n", error); | ||
200 | return error; | ||
201 | } | ||
202 | |||
203 | pwrkey->input = devm_input_allocate_device(&pdev->dev); | ||
204 | if (!pwrkey->input) { | ||
205 | dev_dbg(&pdev->dev, "unable to allocate input device\n"); | ||
206 | return -ENOMEM; | ||
207 | } | ||
208 | |||
209 | input_set_capability(pwrkey->input, EV_KEY, KEY_POWER); | ||
210 | |||
211 | pwrkey->input->name = "pm8941_pwrkey"; | ||
212 | pwrkey->input->phys = "pm8941_pwrkey/input0"; | ||
213 | |||
214 | req_delay = (req_delay << 6) / USEC_PER_SEC; | ||
215 | req_delay = ilog2(req_delay); | ||
216 | |||
217 | error = regmap_update_bits(pwrkey->regmap, | ||
218 | pwrkey->baseaddr + PON_DBC_CTL, | ||
219 | PON_DBC_DELAY_MASK, | ||
220 | req_delay); | ||
221 | if (error) { | ||
222 | dev_err(&pdev->dev, "failed to set debounce: %d\n", error); | ||
223 | return error; | ||
224 | } | ||
225 | |||
226 | error = regmap_update_bits(pwrkey->regmap, | ||
227 | pwrkey->baseaddr + PON_PULL_CTL, | ||
228 | PON_KPDPWR_PULL_UP, | ||
229 | pull_up ? PON_KPDPWR_PULL_UP : 0); | ||
230 | if (error) { | ||
231 | dev_err(&pdev->dev, "failed to set pull: %d\n", error); | ||
232 | return error; | ||
233 | } | ||
234 | |||
235 | error = devm_request_threaded_irq(&pdev->dev, pwrkey->irq, | ||
236 | NULL, pm8941_pwrkey_irq, | ||
237 | IRQF_ONESHOT, | ||
238 | "pm8941_pwrkey", pwrkey); | ||
239 | if (error) { | ||
240 | dev_err(&pdev->dev, "failed requesting IRQ: %d\n", error); | ||
241 | return error; | ||
242 | } | ||
243 | |||
244 | error = input_register_device(pwrkey->input); | ||
245 | if (error) { | ||
246 | dev_err(&pdev->dev, "failed to register input device: %d\n", | ||
247 | error); | ||
248 | return error; | ||
249 | } | ||
250 | |||
251 | pwrkey->reboot_notifier.notifier_call = pm8941_reboot_notify, | ||
252 | error = register_reboot_notifier(&pwrkey->reboot_notifier); | ||
253 | if (error) { | ||
254 | dev_err(&pdev->dev, "failed to register reboot notifier: %d\n", | ||
255 | error); | ||
256 | return error; | ||
257 | } | ||
258 | |||
259 | platform_set_drvdata(pdev, pwrkey); | ||
260 | device_init_wakeup(&pdev->dev, 1); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int pm8941_pwrkey_remove(struct platform_device *pdev) | ||
266 | { | ||
267 | struct pm8941_pwrkey *pwrkey = platform_get_drvdata(pdev); | ||
268 | |||
269 | device_init_wakeup(&pdev->dev, 0); | ||
270 | unregister_reboot_notifier(&pwrkey->reboot_notifier); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static const struct of_device_id pm8941_pwr_key_id_table[] = { | ||
276 | { .compatible = "qcom,pm8941-pwrkey" }, | ||
277 | { } | ||
278 | }; | ||
279 | MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table); | ||
280 | |||
281 | static struct platform_driver pm8941_pwrkey_driver = { | ||
282 | .probe = pm8941_pwrkey_probe, | ||
283 | .remove = pm8941_pwrkey_remove, | ||
284 | .driver = { | ||
285 | .name = "pm8941-pwrkey", | ||
286 | .pm = &pm8941_pwr_key_pm_ops, | ||
287 | .of_match_table = of_match_ptr(pm8941_pwr_key_id_table), | ||
288 | }, | ||
289 | }; | ||
290 | module_platform_driver(pm8941_pwrkey_driver); | ||
291 | |||
292 | MODULE_DESCRIPTION("PM8941 Power Key driver"); | ||
293 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index a28ee70ff158..e82edf810d1f 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c | |||
@@ -50,7 +50,6 @@ static int pwm_beeper_event(struct input_dev *input, | |||
50 | } | 50 | } |
51 | 51 | ||
52 | if (value == 0) { | 52 | if (value == 0) { |
53 | pwm_config(beeper->pwm, 0, 0); | ||
54 | pwm_disable(beeper->pwm); | 53 | pwm_disable(beeper->pwm); |
55 | } else { | 54 | } else { |
56 | period = HZ_TO_NANOSECONDS(value); | 55 | period = HZ_TO_NANOSECONDS(value); |
@@ -169,12 +168,6 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev) | |||
169 | static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops, | 168 | static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops, |
170 | pwm_beeper_suspend, pwm_beeper_resume); | 169 | pwm_beeper_suspend, pwm_beeper_resume); |
171 | 170 | ||
172 | #ifdef CONFIG_PM_SLEEP | ||
173 | #define PWM_BEEPER_PM_OPS (&pwm_beeper_pm_ops) | ||
174 | #else | ||
175 | #define PWM_BEEPER_PM_OPS NULL | ||
176 | #endif | ||
177 | |||
178 | #ifdef CONFIG_OF | 171 | #ifdef CONFIG_OF |
179 | static const struct of_device_id pwm_beeper_match[] = { | 172 | static const struct of_device_id pwm_beeper_match[] = { |
180 | { .compatible = "pwm-beeper", }, | 173 | { .compatible = "pwm-beeper", }, |
@@ -187,7 +180,7 @@ static struct platform_driver pwm_beeper_driver = { | |||
187 | .remove = pwm_beeper_remove, | 180 | .remove = pwm_beeper_remove, |
188 | .driver = { | 181 | .driver = { |
189 | .name = "pwm-beeper", | 182 | .name = "pwm-beeper", |
190 | .pm = PWM_BEEPER_PM_OPS, | 183 | .pm = &pwm_beeper_pm_ops, |
191 | .of_match_table = of_match_ptr(pwm_beeper_match), | 184 | .of_match_table = of_match_ptr(pwm_beeper_match), |
192 | }, | 185 | }, |
193 | }; | 186 | }; |
diff --git a/drivers/input/misc/regulator-haptic.c b/drivers/input/misc/regulator-haptic.c index 132eb914ea3e..6bf3f1082f71 100644 --- a/drivers/input/misc/regulator-haptic.c +++ b/drivers/input/misc/regulator-haptic.c | |||
@@ -245,7 +245,7 @@ static int __maybe_unused regulator_haptic_resume(struct device *dev) | |||
245 | static SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops, | 245 | static SIMPLE_DEV_PM_OPS(regulator_haptic_pm_ops, |
246 | regulator_haptic_suspend, regulator_haptic_resume); | 246 | regulator_haptic_suspend, regulator_haptic_resume); |
247 | 247 | ||
248 | static struct of_device_id regulator_haptic_dt_match[] = { | 248 | static const struct of_device_id regulator_haptic_dt_match[] = { |
249 | { .compatible = "regulator-haptic" }, | 249 | { .compatible = "regulator-haptic" }, |
250 | { /* sentinel */ }, | 250 | { /* sentinel */ }, |
251 | }; | 251 | }; |
diff --git a/drivers/input/misc/tps65218-pwrbutton.c b/drivers/input/misc/tps65218-pwrbutton.c index 54508dec4eb3..a39b62651a4b 100644 --- a/drivers/input/misc/tps65218-pwrbutton.c +++ b/drivers/input/misc/tps65218-pwrbutton.c | |||
@@ -106,7 +106,7 @@ static int tps65218_pwron_probe(struct platform_device *pdev) | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | static struct of_device_id of_tps65218_pwr_match[] = { | 109 | static const struct of_device_id of_tps65218_pwr_match[] = { |
110 | { .compatible = "ti,tps65218-pwrbutton" }, | 110 | { .compatible = "ti,tps65218-pwrbutton" }, |
111 | { }, | 111 | { }, |
112 | }; | 112 | }; |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index d28726a0ef85..e6708f6efb4d 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -153,10 +153,18 @@ static const struct alps_protocol_info alps_v7_protocol_data = { | |||
153 | ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT | 153 | ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT |
154 | }; | 154 | }; |
155 | 155 | ||
156 | static const struct alps_protocol_info alps_v8_protocol_data = { | ||
157 | ALPS_PROTO_V8, 0x18, 0x18, 0 | ||
158 | }; | ||
159 | |||
156 | static void alps_set_abs_params_st(struct alps_data *priv, | 160 | static void alps_set_abs_params_st(struct alps_data *priv, |
157 | struct input_dev *dev1); | 161 | struct input_dev *dev1); |
158 | static void alps_set_abs_params_mt(struct alps_data *priv, | 162 | static void alps_set_abs_params_mt(struct alps_data *priv, |
159 | struct input_dev *dev1); | 163 | struct input_dev *dev1); |
164 | static void alps_set_abs_params_v7(struct alps_data *priv, | ||
165 | struct input_dev *dev1); | ||
166 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
167 | struct input_dev *dev1); | ||
160 | 168 | ||
161 | /* Packet formats are described in Documentation/input/alps.txt */ | 169 | /* Packet formats are described in Documentation/input/alps.txt */ |
162 | 170 | ||
@@ -243,6 +251,14 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) | |||
243 | return; | 251 | return; |
244 | } | 252 | } |
245 | 253 | ||
254 | /* Non interleaved V2 dualpoint has separate stick button bits */ | ||
255 | if (priv->proto_version == ALPS_PROTO_V2 && | ||
256 | priv->flags == (ALPS_PASS | ALPS_DUALPOINT)) { | ||
257 | left |= packet[0] & 1; | ||
258 | right |= packet[0] & 2; | ||
259 | middle |= packet[0] & 4; | ||
260 | } | ||
261 | |||
246 | alps_report_buttons(dev, dev2, left, right, middle); | 262 | alps_report_buttons(dev, dev2, left, right, middle); |
247 | 263 | ||
248 | /* Convert hardware tap to a reasonable Z value */ | 264 | /* Convert hardware tap to a reasonable Z value */ |
@@ -1085,6 +1101,176 @@ static void alps_process_packet_v7(struct psmouse *psmouse) | |||
1085 | alps_process_touchpad_packet_v7(psmouse); | 1101 | alps_process_touchpad_packet_v7(psmouse); |
1086 | } | 1102 | } |
1087 | 1103 | ||
1104 | static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte) | ||
1105 | { | ||
1106 | unsigned char pkt_id = SS4_PACKET_ID_IDLE; | ||
1107 | |||
1108 | if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && | ||
1109 | (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { | ||
1110 | pkt_id = SS4_PACKET_ID_IDLE; | ||
1111 | } else if (!(byte[3] & 0x10)) { | ||
1112 | pkt_id = SS4_PACKET_ID_ONE; | ||
1113 | } else if (!(byte[3] & 0x20)) { | ||
1114 | pkt_id = SS4_PACKET_ID_TWO; | ||
1115 | } else { | ||
1116 | pkt_id = SS4_PACKET_ID_MULTI; | ||
1117 | } | ||
1118 | |||
1119 | return pkt_id; | ||
1120 | } | ||
1121 | |||
1122 | static int alps_decode_ss4_v2(struct alps_fields *f, | ||
1123 | unsigned char *p, struct psmouse *psmouse) | ||
1124 | { | ||
1125 | struct alps_data *priv = psmouse->private; | ||
1126 | unsigned char pkt_id; | ||
1127 | unsigned int no_data_x, no_data_y; | ||
1128 | |||
1129 | pkt_id = alps_get_pkt_id_ss4_v2(p); | ||
1130 | |||
1131 | /* Current packet is 1Finger coordinate packet */ | ||
1132 | switch (pkt_id) { | ||
1133 | case SS4_PACKET_ID_ONE: | ||
1134 | f->mt[0].x = SS4_1F_X_V2(p); | ||
1135 | f->mt[0].y = SS4_1F_Y_V2(p); | ||
1136 | f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f; | ||
1137 | f->fingers = 1; | ||
1138 | f->first_mp = 0; | ||
1139 | f->is_mp = 0; | ||
1140 | break; | ||
1141 | |||
1142 | case SS4_PACKET_ID_TWO: | ||
1143 | if (priv->flags & ALPS_BUTTONPAD) { | ||
1144 | f->mt[0].x = SS4_BTL_MF_X_V2(p, 0); | ||
1145 | f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0); | ||
1146 | f->mt[1].x = SS4_BTL_MF_X_V2(p, 1); | ||
1147 | f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1); | ||
1148 | } else { | ||
1149 | f->mt[0].x = SS4_STD_MF_X_V2(p, 0); | ||
1150 | f->mt[0].y = SS4_STD_MF_Y_V2(p, 0); | ||
1151 | f->mt[1].x = SS4_STD_MF_X_V2(p, 1); | ||
1152 | f->mt[1].y = SS4_STD_MF_Y_V2(p, 1); | ||
1153 | } | ||
1154 | f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0; | ||
1155 | |||
1156 | if (SS4_IS_MF_CONTINUE(p)) { | ||
1157 | f->first_mp = 1; | ||
1158 | } else { | ||
1159 | f->fingers = 2; | ||
1160 | f->first_mp = 0; | ||
1161 | } | ||
1162 | f->is_mp = 0; | ||
1163 | |||
1164 | break; | ||
1165 | |||
1166 | case SS4_PACKET_ID_MULTI: | ||
1167 | if (priv->flags & ALPS_BUTTONPAD) { | ||
1168 | f->mt[2].x = SS4_BTL_MF_X_V2(p, 0); | ||
1169 | f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0); | ||
1170 | f->mt[3].x = SS4_BTL_MF_X_V2(p, 1); | ||
1171 | f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1); | ||
1172 | no_data_x = SS4_MFPACKET_NO_AX_BL; | ||
1173 | no_data_y = SS4_MFPACKET_NO_AY_BL; | ||
1174 | } else { | ||
1175 | f->mt[2].x = SS4_STD_MF_X_V2(p, 0); | ||
1176 | f->mt[2].y = SS4_STD_MF_Y_V2(p, 0); | ||
1177 | f->mt[3].x = SS4_STD_MF_X_V2(p, 1); | ||
1178 | f->mt[3].y = SS4_STD_MF_Y_V2(p, 1); | ||
1179 | no_data_x = SS4_MFPACKET_NO_AX; | ||
1180 | no_data_y = SS4_MFPACKET_NO_AY; | ||
1181 | } | ||
1182 | |||
1183 | f->first_mp = 0; | ||
1184 | f->is_mp = 1; | ||
1185 | |||
1186 | if (SS4_IS_5F_DETECTED(p)) { | ||
1187 | f->fingers = 5; | ||
1188 | } else if (f->mt[3].x == no_data_x && | ||
1189 | f->mt[3].y == no_data_y) { | ||
1190 | f->mt[3].x = 0; | ||
1191 | f->mt[3].y = 0; | ||
1192 | f->fingers = 3; | ||
1193 | } else { | ||
1194 | f->fingers = 4; | ||
1195 | } | ||
1196 | break; | ||
1197 | |||
1198 | case SS4_PACKET_ID_IDLE: | ||
1199 | default: | ||
1200 | memset(f, 0, sizeof(struct alps_fields)); | ||
1201 | break; | ||
1202 | } | ||
1203 | |||
1204 | f->left = !!(SS4_BTN_V2(p) & 0x01); | ||
1205 | if (!(priv->flags & ALPS_BUTTONPAD)) { | ||
1206 | f->right = !!(SS4_BTN_V2(p) & 0x02); | ||
1207 | f->middle = !!(SS4_BTN_V2(p) & 0x04); | ||
1208 | } | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | static void alps_process_packet_ss4_v2(struct psmouse *psmouse) | ||
1214 | { | ||
1215 | struct alps_data *priv = psmouse->private; | ||
1216 | unsigned char *packet = psmouse->packet; | ||
1217 | struct input_dev *dev = psmouse->dev; | ||
1218 | struct alps_fields *f = &priv->f; | ||
1219 | |||
1220 | memset(f, 0, sizeof(struct alps_fields)); | ||
1221 | priv->decode_fields(f, packet, psmouse); | ||
1222 | if (priv->multi_packet) { | ||
1223 | /* | ||
1224 | * Sometimes the first packet will indicate a multi-packet | ||
1225 | * sequence, but sometimes the next multi-packet would not | ||
1226 | * come. Check for this, and when it happens process the | ||
1227 | * position packet as usual. | ||
1228 | */ | ||
1229 | if (f->is_mp) { | ||
1230 | /* Now process the 1st packet */ | ||
1231 | priv->decode_fields(f, priv->multi_data, psmouse); | ||
1232 | } else { | ||
1233 | priv->multi_packet = 0; | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | /* | ||
1238 | * "f.is_mp" would always be '0' after merging the 1st and 2nd packet. | ||
1239 | * When it is set, it means 2nd packet comes without 1st packet come. | ||
1240 | */ | ||
1241 | if (f->is_mp) | ||
1242 | return; | ||
1243 | |||
1244 | /* Save the first packet */ | ||
1245 | if (!priv->multi_packet && f->first_mp) { | ||
1246 | priv->multi_packet = 1; | ||
1247 | memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); | ||
1248 | return; | ||
1249 | } | ||
1250 | |||
1251 | priv->multi_packet = 0; | ||
1252 | |||
1253 | alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4); | ||
1254 | |||
1255 | input_mt_report_finger_count(dev, f->fingers); | ||
1256 | |||
1257 | input_report_key(dev, BTN_LEFT, f->left); | ||
1258 | input_report_key(dev, BTN_RIGHT, f->right); | ||
1259 | input_report_key(dev, BTN_MIDDLE, f->middle); | ||
1260 | |||
1261 | input_report_abs(dev, ABS_PRESSURE, f->pressure); | ||
1262 | input_sync(dev); | ||
1263 | } | ||
1264 | |||
1265 | static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) | ||
1266 | { | ||
1267 | if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08)) | ||
1268 | return false; | ||
1269 | if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0)) | ||
1270 | return false; | ||
1271 | return true; | ||
1272 | } | ||
1273 | |||
1088 | static DEFINE_MUTEX(alps_mutex); | 1274 | static DEFINE_MUTEX(alps_mutex); |
1089 | 1275 | ||
1090 | static void alps_register_bare_ps2_mouse(struct work_struct *work) | 1276 | static void alps_register_bare_ps2_mouse(struct work_struct *work) |
@@ -1154,12 +1340,31 @@ out: | |||
1154 | mutex_unlock(&alps_mutex); | 1340 | mutex_unlock(&alps_mutex); |
1155 | } | 1341 | } |
1156 | 1342 | ||
1157 | static void alps_report_bare_ps2_packet(struct input_dev *dev, | 1343 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, |
1158 | unsigned char packet[], | 1344 | unsigned char packet[], |
1159 | bool report_buttons) | 1345 | bool report_buttons) |
1160 | { | 1346 | { |
1347 | struct alps_data *priv = psmouse->private; | ||
1348 | struct input_dev *dev, *dev2 = NULL; | ||
1349 | |||
1350 | /* Figure out which device to use to report the bare packet */ | ||
1351 | if (priv->proto_version == ALPS_PROTO_V2 && | ||
1352 | (priv->flags & ALPS_DUALPOINT)) { | ||
1353 | /* On V2 devices the DualPoint Stick reports bare packets */ | ||
1354 | dev = priv->dev2; | ||
1355 | dev2 = psmouse->dev; | ||
1356 | } else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) { | ||
1357 | /* Register dev3 mouse if we received PS/2 packet first time */ | ||
1358 | if (!IS_ERR(priv->dev3)) | ||
1359 | psmouse_queue_work(psmouse, &priv->dev3_register_work, | ||
1360 | 0); | ||
1361 | return; | ||
1362 | } else { | ||
1363 | dev = priv->dev3; | ||
1364 | } | ||
1365 | |||
1161 | if (report_buttons) | 1366 | if (report_buttons) |
1162 | alps_report_buttons(dev, NULL, | 1367 | alps_report_buttons(dev, dev2, |
1163 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | 1368 | packet[0] & 1, packet[0] & 2, packet[0] & 4); |
1164 | 1369 | ||
1165 | input_report_rel(dev, REL_X, | 1370 | input_report_rel(dev, REL_X, |
@@ -1232,8 +1437,8 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | |||
1232 | * de-synchronization. | 1437 | * de-synchronization. |
1233 | */ | 1438 | */ |
1234 | 1439 | ||
1235 | alps_report_bare_ps2_packet(priv->dev2, | 1440 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], |
1236 | &psmouse->packet[3], false); | 1441 | false); |
1237 | 1442 | ||
1238 | /* | 1443 | /* |
1239 | * Continue with the standard ALPS protocol handling, | 1444 | * Continue with the standard ALPS protocol handling, |
@@ -1287,20 +1492,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1287 | * a device connected to the external PS/2 port. Because bare PS/2 | 1492 | * a device connected to the external PS/2 port. Because bare PS/2 |
1288 | * protocol does not have enough constant bits to self-synchronize | 1493 | * protocol does not have enough constant bits to self-synchronize |
1289 | * properly we only do this if the device is fully synchronized. | 1494 | * properly we only do this if the device is fully synchronized. |
1495 | * Can not distinguish V8's first byte from PS/2 packet's | ||
1290 | */ | 1496 | */ |
1291 | if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) { | 1497 | if (priv->proto_version != ALPS_PROTO_V8 && |
1292 | 1498 | !psmouse->out_of_sync_cnt && | |
1293 | /* Register dev3 mouse if we received PS/2 packet first time */ | 1499 | (psmouse->packet[0] & 0xc8) == 0x08) { |
1294 | if (unlikely(!priv->dev3)) | ||
1295 | psmouse_queue_work(psmouse, | ||
1296 | &priv->dev3_register_work, 0); | ||
1297 | 1500 | ||
1298 | if (psmouse->pktcnt == 3) { | 1501 | if (psmouse->pktcnt == 3) { |
1299 | /* Once dev3 mouse device is registered report data */ | 1502 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
1300 | if (likely(!IS_ERR_OR_NULL(priv->dev3))) | 1503 | true); |
1301 | alps_report_bare_ps2_packet(priv->dev3, | ||
1302 | psmouse->packet, | ||
1303 | true); | ||
1304 | return PSMOUSE_FULL_PACKET; | 1504 | return PSMOUSE_FULL_PACKET; |
1305 | } | 1505 | } |
1306 | return PSMOUSE_GOOD_DATA; | 1506 | return PSMOUSE_GOOD_DATA; |
@@ -1345,8 +1545,10 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
1345 | return PSMOUSE_BAD_DATA; | 1545 | return PSMOUSE_BAD_DATA; |
1346 | } | 1546 | } |
1347 | 1547 | ||
1348 | if (priv->proto_version == ALPS_PROTO_V7 && | 1548 | if ((priv->proto_version == ALPS_PROTO_V7 && |
1349 | !alps_is_valid_package_v7(psmouse)) { | 1549 | !alps_is_valid_package_v7(psmouse)) || |
1550 | (priv->proto_version == ALPS_PROTO_V8 && | ||
1551 | !alps_is_valid_package_ss4_v2(psmouse))) { | ||
1350 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 1552 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
1351 | psmouse->pktcnt - 1, | 1553 | psmouse->pktcnt - 1, |
1352 | psmouse->packet[psmouse->pktcnt - 1]); | 1554 | psmouse->packet[psmouse->pktcnt - 1]); |
@@ -2121,6 +2323,88 @@ error: | |||
2121 | return -1; | 2323 | return -1; |
2122 | } | 2324 | } |
2123 | 2325 | ||
2326 | static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse, | ||
2327 | unsigned char index, unsigned char otp[]) | ||
2328 | { | ||
2329 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2330 | |||
2331 | switch (index) { | ||
2332 | case 0: | ||
2333 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2334 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2335 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
2336 | return -1; | ||
2337 | |||
2338 | break; | ||
2339 | |||
2340 | case 1: | ||
2341 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
2342 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) || | ||
2343 | ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO)) | ||
2344 | return -1; | ||
2345 | |||
2346 | break; | ||
2347 | } | ||
2348 | |||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2352 | static int alps_update_device_area_ss4_v2(unsigned char otp[][4], | ||
2353 | struct alps_data *priv) | ||
2354 | { | ||
2355 | int num_x_electrode; | ||
2356 | int num_y_electrode; | ||
2357 | int x_pitch, y_pitch, x_phys, y_phys; | ||
2358 | |||
2359 | num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); | ||
2360 | num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); | ||
2361 | |||
2362 | priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
2363 | priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; | ||
2364 | |||
2365 | x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; | ||
2366 | y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; | ||
2367 | |||
2368 | x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */ | ||
2369 | y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */ | ||
2370 | |||
2371 | priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */ | ||
2372 | priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */ | ||
2373 | |||
2374 | return 0; | ||
2375 | } | ||
2376 | |||
2377 | static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], | ||
2378 | struct alps_data *priv) | ||
2379 | { | ||
2380 | unsigned char is_btnless; | ||
2381 | |||
2382 | is_btnless = (otp[1][1] >> 3) & 0x01; | ||
2383 | |||
2384 | if (is_btnless) | ||
2385 | priv->flags |= ALPS_BUTTONPAD; | ||
2386 | |||
2387 | return 0; | ||
2388 | } | ||
2389 | |||
2390 | static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, | ||
2391 | struct alps_data *priv) | ||
2392 | { | ||
2393 | unsigned char otp[2][4]; | ||
2394 | |||
2395 | memset(otp, 0, sizeof(otp)); | ||
2396 | |||
2397 | if (alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]) || | ||
2398 | alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0])) | ||
2399 | return -1; | ||
2400 | |||
2401 | alps_update_device_area_ss4_v2(otp, priv); | ||
2402 | |||
2403 | alps_update_btn_info_ss4_v2(otp, priv); | ||
2404 | |||
2405 | return 0; | ||
2406 | } | ||
2407 | |||
2124 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, | 2408 | static int alps_dolphin_get_device_area(struct psmouse *psmouse, |
2125 | struct alps_data *priv) | 2409 | struct alps_data *priv) |
2126 | { | 2410 | { |
@@ -2213,6 +2497,35 @@ error: | |||
2213 | return ret; | 2497 | return ret; |
2214 | } | 2498 | } |
2215 | 2499 | ||
2500 | static int alps_hw_init_ss4_v2(struct psmouse *psmouse) | ||
2501 | { | ||
2502 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
2503 | char param[2] = {0x64, 0x28}; | ||
2504 | int ret = -1; | ||
2505 | |||
2506 | /* enter absolute mode */ | ||
2507 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2508 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
2509 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
2510 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) { | ||
2511 | goto error; | ||
2512 | } | ||
2513 | |||
2514 | /* T.B.D. Decread noise packet number, delete in the future */ | ||
2515 | if (alps_exit_command_mode(psmouse) || | ||
2516 | alps_enter_command_mode(psmouse) || | ||
2517 | alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) { | ||
2518 | goto error; | ||
2519 | } | ||
2520 | alps_exit_command_mode(psmouse); | ||
2521 | |||
2522 | return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
2523 | |||
2524 | error: | ||
2525 | alps_exit_command_mode(psmouse); | ||
2526 | return ret; | ||
2527 | } | ||
2528 | |||
2216 | static int alps_set_protocol(struct psmouse *psmouse, | 2529 | static int alps_set_protocol(struct psmouse *psmouse, |
2217 | struct alps_data *priv, | 2530 | struct alps_data *priv, |
2218 | const struct alps_protocol_info *protocol) | 2531 | const struct alps_protocol_info *protocol) |
@@ -2281,10 +2594,12 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2281 | priv->set_abs_params = alps_set_abs_params_mt; | 2594 | priv->set_abs_params = alps_set_abs_params_mt; |
2282 | priv->nibble_commands = alps_v3_nibble_commands; | 2595 | priv->nibble_commands = alps_v3_nibble_commands; |
2283 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2596 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2284 | priv->x_max = 1360; | ||
2285 | priv->y_max = 660; | ||
2286 | priv->x_bits = 23; | 2597 | priv->x_bits = 23; |
2287 | priv->y_bits = 12; | 2598 | priv->y_bits = 12; |
2599 | |||
2600 | if (alps_dolphin_get_device_area(psmouse, priv)) | ||
2601 | return -EIO; | ||
2602 | |||
2288 | break; | 2603 | break; |
2289 | 2604 | ||
2290 | case ALPS_PROTO_V6: | 2605 | case ALPS_PROTO_V6: |
@@ -2300,17 +2615,29 @@ static int alps_set_protocol(struct psmouse *psmouse, | |||
2300 | priv->hw_init = alps_hw_init_v7; | 2615 | priv->hw_init = alps_hw_init_v7; |
2301 | priv->process_packet = alps_process_packet_v7; | 2616 | priv->process_packet = alps_process_packet_v7; |
2302 | priv->decode_fields = alps_decode_packet_v7; | 2617 | priv->decode_fields = alps_decode_packet_v7; |
2303 | priv->set_abs_params = alps_set_abs_params_mt; | 2618 | priv->set_abs_params = alps_set_abs_params_v7; |
2304 | priv->nibble_commands = alps_v3_nibble_commands; | 2619 | priv->nibble_commands = alps_v3_nibble_commands; |
2305 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | 2620 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; |
2306 | 2621 | priv->x_max = 0xfff; | |
2307 | if (alps_dolphin_get_device_area(psmouse, priv)) | 2622 | priv->y_max = 0x7ff; |
2308 | return -EIO; | ||
2309 | 2623 | ||
2310 | if (priv->fw_ver[1] != 0xba) | 2624 | if (priv->fw_ver[1] != 0xba) |
2311 | priv->flags |= ALPS_BUTTONPAD; | 2625 | priv->flags |= ALPS_BUTTONPAD; |
2312 | 2626 | ||
2313 | break; | 2627 | break; |
2628 | |||
2629 | case ALPS_PROTO_V8: | ||
2630 | priv->hw_init = alps_hw_init_ss4_v2; | ||
2631 | priv->process_packet = alps_process_packet_ss4_v2; | ||
2632 | priv->decode_fields = alps_decode_ss4_v2; | ||
2633 | priv->set_abs_params = alps_set_abs_params_ss4_v2; | ||
2634 | priv->nibble_commands = alps_v3_nibble_commands; | ||
2635 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
2636 | |||
2637 | if (alps_set_defaults_ss4_v2(psmouse, priv)) | ||
2638 | return -EIO; | ||
2639 | |||
2640 | break; | ||
2314 | } | 2641 | } |
2315 | 2642 | ||
2316 | return 0; | 2643 | return 0; |
@@ -2379,6 +2706,9 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
2379 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && | 2706 | } else if (ec[0] == 0x88 && ec[1] == 0x07 && |
2380 | ec[2] >= 0x90 && ec[2] <= 0x9d) { | 2707 | ec[2] >= 0x90 && ec[2] <= 0x9d) { |
2381 | protocol = &alps_v3_protocol_data; | 2708 | protocol = &alps_v3_protocol_data; |
2709 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && | ||
2710 | e7[2] == 0x14 && ec[1] == 0x02) { | ||
2711 | protocol = &alps_v8_protocol_data; | ||
2382 | } else { | 2712 | } else { |
2383 | psmouse_dbg(psmouse, | 2713 | psmouse_dbg(psmouse, |
2384 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); | 2714 | "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec); |
@@ -2427,10 +2757,11 @@ static void alps_set_abs_params_st(struct alps_data *priv, | |||
2427 | { | 2757 | { |
2428 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); | 2758 | input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); |
2429 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); | 2759 | input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); |
2760 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2430 | } | 2761 | } |
2431 | 2762 | ||
2432 | static void alps_set_abs_params_mt(struct alps_data *priv, | 2763 | static void alps_set_abs_params_mt_common(struct alps_data *priv, |
2433 | struct input_dev *dev1) | 2764 | struct input_dev *dev1) |
2434 | { | 2765 | { |
2435 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); | 2766 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); |
2436 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); | 2767 | input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); |
@@ -2438,15 +2769,44 @@ static void alps_set_abs_params_mt(struct alps_data *priv, | |||
2438 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); | 2769 | input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res); |
2439 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); | 2770 | input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res); |
2440 | 2771 | ||
2441 | input_mt_init_slots(dev1, MAX_TOUCHES, INPUT_MT_POINTER | | ||
2442 | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2443 | |||
2444 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 2772 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
2445 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); | 2773 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); |
2774 | } | ||
2775 | |||
2776 | static void alps_set_abs_params_mt(struct alps_data *priv, | ||
2777 | struct input_dev *dev1) | ||
2778 | { | ||
2779 | alps_set_abs_params_mt_common(priv, dev1); | ||
2780 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2781 | |||
2782 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2783 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2784 | INPUT_MT_TRACK | INPUT_MT_SEMI_MT); | ||
2785 | } | ||
2446 | 2786 | ||
2447 | /* V7 is real multi-touch */ | 2787 | static void alps_set_abs_params_v7(struct alps_data *priv, |
2448 | if (priv->proto_version == ALPS_PROTO_V7) | 2788 | struct input_dev *dev1) |
2449 | clear_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | 2789 | { |
2790 | alps_set_abs_params_mt_common(priv, dev1); | ||
2791 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2792 | |||
2793 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2794 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2795 | INPUT_MT_TRACK); | ||
2796 | |||
2797 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2798 | } | ||
2799 | |||
2800 | static void alps_set_abs_params_ss4_v2(struct alps_data *priv, | ||
2801 | struct input_dev *dev1) | ||
2802 | { | ||
2803 | alps_set_abs_params_mt_common(priv, dev1); | ||
2804 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2805 | set_bit(BTN_TOOL_QUINTTAP, dev1->keybit); | ||
2806 | |||
2807 | input_mt_init_slots(dev1, MAX_TOUCHES, | ||
2808 | INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | | ||
2809 | INPUT_MT_TRACK); | ||
2450 | } | 2810 | } |
2451 | 2811 | ||
2452 | int alps_init(struct psmouse *psmouse) | 2812 | int alps_init(struct psmouse *psmouse) |
@@ -2479,9 +2839,6 @@ int alps_init(struct psmouse *psmouse) | |||
2479 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 2839 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
2480 | 2840 | ||
2481 | priv->set_abs_params(priv, dev1); | 2841 | priv->set_abs_params(priv, dev1); |
2482 | /* No pressure on V7 */ | ||
2483 | if (priv->proto_version != ALPS_PROTO_V7) | ||
2484 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | ||
2485 | 2842 | ||
2486 | if (priv->flags & ALPS_WHEEL) { | 2843 | if (priv->flags & ALPS_WHEEL) { |
2487 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 2844 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
@@ -2605,8 +2962,10 @@ int alps_detect(struct psmouse *psmouse, bool set_properties) | |||
2605 | return -ENOMEM; | 2962 | return -ENOMEM; |
2606 | 2963 | ||
2607 | error = alps_identify(psmouse, priv); | 2964 | error = alps_identify(psmouse, priv); |
2608 | if (error) | 2965 | if (error) { |
2966 | kfree(priv); | ||
2609 | return error; | 2967 | return error; |
2968 | } | ||
2610 | 2969 | ||
2611 | if (set_properties) { | 2970 | if (set_properties) { |
2612 | psmouse->vendor = "ALPS"; | 2971 | psmouse->vendor = "ALPS"; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 02513c0502fc..6dfdccc3a7c6 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -22,14 +22,90 @@ | |||
22 | #define ALPS_PROTO_V5 0x500 | 22 | #define ALPS_PROTO_V5 0x500 |
23 | #define ALPS_PROTO_V6 0x600 | 23 | #define ALPS_PROTO_V6 0x600 |
24 | #define ALPS_PROTO_V7 0x700 /* t3btl t4s */ | 24 | #define ALPS_PROTO_V7 0x700 /* t3btl t4s */ |
25 | #define ALPS_PROTO_V8 0x800 /* SS4btl SS4s */ | ||
25 | 26 | ||
26 | #define MAX_TOUCHES 2 | 27 | #define MAX_TOUCHES 4 |
27 | 28 | ||
28 | #define DOLPHIN_COUNT_PER_ELECTRODE 64 | 29 | #define DOLPHIN_COUNT_PER_ELECTRODE 64 |
29 | #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ | 30 | #define DOLPHIN_PROFILE_XOFFSET 8 /* x-electrode offset */ |
30 | #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ | 31 | #define DOLPHIN_PROFILE_YOFFSET 1 /* y-electrode offset */ |
31 | 32 | ||
32 | /* | 33 | /* |
34 | * enum SS4_PACKET_ID - defines the packet type for V8 | ||
35 | * SS4_PACKET_ID_IDLE: There's no finger and no button activity. | ||
36 | * SS4_PACKET_ID_ONE: There's one finger on touchpad | ||
37 | * or there's button activities. | ||
38 | * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad | ||
39 | * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad | ||
40 | */ | ||
41 | enum SS4_PACKET_ID { | ||
42 | SS4_PACKET_ID_IDLE = 0, | ||
43 | SS4_PACKET_ID_ONE, | ||
44 | SS4_PACKET_ID_TWO, | ||
45 | SS4_PACKET_ID_MULTI, | ||
46 | }; | ||
47 | |||
48 | #define SS4_COUNT_PER_ELECTRODE 256 | ||
49 | #define SS4_NUMSENSOR_XOFFSET 7 | ||
50 | #define SS4_NUMSENSOR_YOFFSET 7 | ||
51 | #define SS4_MIN_PITCH_MM 50 | ||
52 | |||
53 | #define SS4_MASK_NORMAL_BUTTONS 0x07 | ||
54 | |||
55 | #define SS4_1F_X_V2(_b) ((_b[0] & 0x0007) | \ | ||
56 | ((_b[1] << 3) & 0x0078) | \ | ||
57 | ((_b[1] << 2) & 0x0380) | \ | ||
58 | ((_b[2] << 5) & 0x1C00) \ | ||
59 | ) | ||
60 | |||
61 | #define SS4_1F_Y_V2(_b) (((_b[2]) & 0x000F) | \ | ||
62 | ((_b[3] >> 2) & 0x0030) | \ | ||
63 | ((_b[4] << 6) & 0x03C0) | \ | ||
64 | ((_b[4] << 5) & 0x0C00) \ | ||
65 | ) | ||
66 | |||
67 | #define SS4_1F_Z_V2(_b) (((_b[5]) & 0x0F) | \ | ||
68 | ((_b[5] >> 1) & 0x70) | \ | ||
69 | ((_b[4]) & 0x80) \ | ||
70 | ) | ||
71 | |||
72 | #define SS4_1F_LFB_V2(_b) (((_b[2] >> 4) & 0x01) == 0x01) | ||
73 | |||
74 | #define SS4_MF_LF_V2(_b, _i) ((_b[1 + (_i) * 3] & 0x0004) == 0x0004) | ||
75 | |||
76 | #define SS4_BTN_V2(_b) ((_b[0] >> 5) & SS4_MASK_NORMAL_BUTTONS) | ||
77 | |||
78 | #define SS4_STD_MF_X_V2(_b, _i) (((_b[0 + (_i) * 3] << 5) & 0x00E0) | \ | ||
79 | ((_b[1 + _i * 3] << 5) & 0x1F00) \ | ||
80 | ) | ||
81 | |||
82 | #define SS4_STD_MF_Y_V2(_b, _i) (((_b[1 + (_i) * 3] << 3) & 0x0010) | \ | ||
83 | ((_b[2 + (_i) * 3] << 5) & 0x01E0) | \ | ||
84 | ((_b[2 + (_i) * 3] << 4) & 0x0E00) \ | ||
85 | ) | ||
86 | |||
87 | #define SS4_BTL_MF_X_V2(_b, _i) (SS4_STD_MF_X_V2(_b, _i) | \ | ||
88 | ((_b[0 + (_i) * 3] >> 3) & 0x0010) \ | ||
89 | ) | ||
90 | |||
91 | #define SS4_BTL_MF_Y_V2(_b, _i) (SS4_STD_MF_Y_V2(_b, _i) | \ | ||
92 | ((_b[0 + (_i) * 3] >> 3) & 0x0008) \ | ||
93 | ) | ||
94 | |||
95 | #define SS4_MF_Z_V2(_b, _i) (((_b[1 + (_i) * 3]) & 0x0001) | \ | ||
96 | ((_b[1 + (_i) * 3] >> 1) & 0x0002) \ | ||
97 | ) | ||
98 | |||
99 | #define SS4_IS_MF_CONTINUE(_b) ((_b[2] & 0x10) == 0x10) | ||
100 | #define SS4_IS_5F_DETECTED(_b) ((_b[2] & 0x10) == 0x10) | ||
101 | |||
102 | |||
103 | #define SS4_MFPACKET_NO_AX 8160 /* X-Coordinate value */ | ||
104 | #define SS4_MFPACKET_NO_AY 4080 /* Y-Coordinate value */ | ||
105 | #define SS4_MFPACKET_NO_AX_BL 8176 /* Buttonless X-Coordinate value */ | ||
106 | #define SS4_MFPACKET_NO_AY_BL 4088 /* Buttonless Y-Coordinate value */ | ||
107 | |||
108 | /* | ||
33 | * enum V7_PACKET_ID - defines the packet type for V7 | 109 | * enum V7_PACKET_ID - defines the packet type for V7 |
34 | * V7_PACKET_ID_IDLE: There's no finger and no button activity. | 110 | * V7_PACKET_ID_IDLE: There's no finger and no button activity. |
35 | * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad | 111 | * V7_PACKET_ID_TWO: There's one or two non-resting fingers on touchpad |
diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 77e9d70a986b..1e2291c378fe 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/input/mt.h> | 20 | #include <linux/input/mt.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/unaligned/access_ok.h> | 23 | #include <asm/unaligned.h> |
24 | #include "cyapa.h" | 24 | #include "cyapa.h" |
25 | 25 | ||
26 | 26 | ||
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index ddf5393a1180..5b611dd71e79 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/completion.h> | 18 | #include <linux/completion.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/unaligned/access_ok.h> | 20 | #include <asm/unaligned.h> |
21 | #include <linux/crc-itu-t.h> | 21 | #include <linux/crc-itu-t.h> |
22 | #include "cyapa.h" | 22 | #include "cyapa.h" |
23 | 23 | ||
@@ -1926,7 +1926,7 @@ static int cyapa_gen5_read_idac_data(struct cyapa *cyapa, | |||
1926 | electrodes_tx = cyapa->electrodes_x; | 1926 | electrodes_tx = cyapa->electrodes_x; |
1927 | max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) & | 1927 | max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) & |
1928 | ~7u) * electrodes_tx; | 1928 | ~7u) * electrodes_tx; |
1929 | } else if (idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) { | 1929 | } else { |
1930 | offset = 2; | 1930 | offset = 2; |
1931 | max_element_cnt = cyapa->electrodes_x + | 1931 | max_element_cnt = cyapa->electrodes_x + |
1932 | cyapa->electrodes_y; | 1932 | cyapa->electrodes_y; |
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index e100c1b31597..9b2dc015f20c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h | |||
@@ -17,7 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifndef _ELAN_I2C_H | 19 | #ifndef _ELAN_I2C_H |
20 | #define _ELAN_i2C_H | 20 | #define _ELAN_I2C_H |
21 | 21 | ||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | 23 | ||
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 7ce8bfe22d7e..375d98f47483 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c | |||
@@ -99,7 +99,7 @@ static int elan_enable_power(struct elan_tp_data *data) | |||
99 | error = regulator_enable(data->vcc); | 99 | error = regulator_enable(data->vcc); |
100 | if (error) { | 100 | if (error) { |
101 | dev_err(&data->client->dev, | 101 | dev_err(&data->client->dev, |
102 | "Failed to enable regulator: %d\n", error); | 102 | "failed to enable regulator: %d\n", error); |
103 | return error; | 103 | return error; |
104 | } | 104 | } |
105 | 105 | ||
@@ -111,6 +111,7 @@ static int elan_enable_power(struct elan_tp_data *data) | |||
111 | msleep(30); | 111 | msleep(30); |
112 | } while (--repeat > 0); | 112 | } while (--repeat > 0); |
113 | 113 | ||
114 | dev_err(&data->client->dev, "failed to enable power: %d\n", error); | ||
114 | return error; | 115 | return error; |
115 | } | 116 | } |
116 | 117 | ||
@@ -125,7 +126,7 @@ static int elan_disable_power(struct elan_tp_data *data) | |||
125 | error = regulator_disable(data->vcc); | 126 | error = regulator_disable(data->vcc); |
126 | if (error) { | 127 | if (error) { |
127 | dev_err(&data->client->dev, | 128 | dev_err(&data->client->dev, |
128 | "Failed to disable regulator: %d\n", | 129 | "failed to disable regulator: %d\n", |
129 | error); | 130 | error); |
130 | /* Attempt to power the chip back up */ | 131 | /* Attempt to power the chip back up */ |
131 | data->ops->power_control(data->client, true); | 132 | data->ops->power_control(data->client, true); |
@@ -138,6 +139,7 @@ static int elan_disable_power(struct elan_tp_data *data) | |||
138 | msleep(30); | 139 | msleep(30); |
139 | } while (--repeat > 0); | 140 | } while (--repeat > 0); |
140 | 141 | ||
142 | dev_err(&data->client->dev, "failed to disable power: %d\n", error); | ||
141 | return error; | 143 | return error; |
142 | } | 144 | } |
143 | 145 | ||
@@ -196,7 +198,6 @@ static int elan_initialize(struct elan_tp_data *data) | |||
196 | if (!error) | 198 | if (!error) |
197 | return 0; | 199 | return 0; |
198 | 200 | ||
199 | repeat--; | ||
200 | msleep(30); | 201 | msleep(30); |
201 | } while (--repeat > 0); | 202 | } while (--repeat > 0); |
202 | 203 | ||
@@ -1084,16 +1085,18 @@ static int __maybe_unused elan_resume(struct device *dev) | |||
1084 | } | 1085 | } |
1085 | 1086 | ||
1086 | error = elan_enable_power(data); | 1087 | error = elan_enable_power(data); |
1087 | if (error) | 1088 | if (error) { |
1088 | dev_err(dev, "power up when resuming failed: %d\n", error); | 1089 | dev_err(dev, "power up when resuming failed: %d\n", error); |
1090 | goto err; | ||
1091 | } | ||
1089 | 1092 | ||
1090 | error = elan_initialize(data); | 1093 | error = elan_initialize(data); |
1091 | if (error) | 1094 | if (error) |
1092 | dev_err(dev, "initialize when resuming failed: %d\n", error); | 1095 | dev_err(dev, "initialize when resuming failed: %d\n", error); |
1093 | 1096 | ||
1097 | err: | ||
1094 | enable_irq(data->client->irq); | 1098 | enable_irq(data->client->irq); |
1095 | 1099 | return error; | |
1096 | return 0; | ||
1097 | } | 1100 | } |
1098 | 1101 | ||
1099 | static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); | 1102 | static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); |
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 029941f861af..6cf0def6d35e 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c | |||
@@ -117,7 +117,15 @@ static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd) | |||
117 | int ret; | 117 | int ret; |
118 | 118 | ||
119 | ret = i2c_transfer(client->adapter, &msg, 1); | 119 | ret = i2c_transfer(client->adapter, &msg, 1); |
120 | return ret == 1 ? 0 : (ret < 0 ? ret : -EIO); | 120 | if (ret != 1) { |
121 | if (ret >= 0) | ||
122 | ret = -EIO; | ||
123 | dev_err(&client->dev, "writing cmd (0x%04x) failed: %d\n", | ||
124 | reg, ret); | ||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
121 | } | 129 | } |
122 | 130 | ||
123 | static int elan_i2c_initialize(struct i2c_client *client) | 131 | static int elan_i2c_initialize(struct i2c_client *client) |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6e22682c8255..991dc6b20a58 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -893,6 +893,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | |||
893 | } | 893 | } |
894 | 894 | ||
895 | /* | 895 | /* |
896 | * This writes the reg_07 value again to the hardware at the end of every | ||
897 | * set_rate call because the register loses its value. reg_07 allows setting | ||
898 | * absolute mode on v4 hardware | ||
899 | */ | ||
900 | static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse, | ||
901 | unsigned int rate) | ||
902 | { | ||
903 | struct elantech_data *etd = psmouse->private; | ||
904 | |||
905 | etd->original_set_rate(psmouse, rate); | ||
906 | if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) | ||
907 | psmouse_err(psmouse, "restoring reg_07 failed\n"); | ||
908 | } | ||
909 | |||
910 | /* | ||
896 | * Put the touchpad into absolute mode | 911 | * Put the touchpad into absolute mode |
897 | */ | 912 | */ |
898 | static int elantech_set_absolute_mode(struct psmouse *psmouse) | 913 | static int elantech_set_absolute_mode(struct psmouse *psmouse) |
@@ -1094,6 +1109,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
1094 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons | 1109 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons |
1095 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons | 1110 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons |
1096 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons | 1111 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons |
1112 | * Asus TP500LN 0x381f17 10, 14, 0e clickpad | ||
1113 | * Asus X750JN 0x381f17 10, 14, 0e clickpad | ||
1097 | * Asus UX31 0x361f00 20, 15, 0e clickpad | 1114 | * Asus UX31 0x361f00 20, 15, 0e clickpad |
1098 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad | 1115 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad |
1099 | * Avatar AVIU-145A2 0x361f00 ? clickpad | 1116 | * Avatar AVIU-145A2 0x361f00 ? clickpad |
@@ -1635,6 +1652,11 @@ int elantech_init(struct psmouse *psmouse) | |||
1635 | goto init_fail; | 1652 | goto init_fail; |
1636 | } | 1653 | } |
1637 | 1654 | ||
1655 | if (etd->fw_version == 0x381f17) { | ||
1656 | etd->original_set_rate = psmouse->set_rate; | ||
1657 | psmouse->set_rate = elantech_set_rate_restore_reg_07; | ||
1658 | } | ||
1659 | |||
1638 | if (elantech_set_input_params(psmouse)) { | 1660 | if (elantech_set_input_params(psmouse)) { |
1639 | psmouse_err(psmouse, "failed to query touchpad range.\n"); | 1661 | psmouse_err(psmouse, "failed to query touchpad range.\n"); |
1640 | goto init_fail; | 1662 | goto init_fail; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 6f3afec02f03..f965d1569cc3 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -142,6 +142,7 @@ struct elantech_data { | |||
142 | struct finger_pos mt[ETP_MAX_FINGERS]; | 142 | struct finger_pos mt[ETP_MAX_FINGERS]; |
143 | unsigned char parity[256]; | 143 | unsigned char parity[256]; |
144 | int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); | 144 | int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); |
145 | void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate); | ||
145 | }; | 146 | }; |
146 | 147 | ||
147 | #ifdef CONFIG_MOUSE_PS2_ELANTECH | 148 | #ifdef CONFIG_MOUSE_PS2_ELANTECH |
diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index 757f78a94aec..23d259416f2f 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c | |||
@@ -67,9 +67,6 @@ static void focaltech_reset(struct psmouse *psmouse) | |||
67 | 67 | ||
68 | #define FOC_MAX_FINGERS 5 | 68 | #define FOC_MAX_FINGERS 5 |
69 | 69 | ||
70 | #define FOC_MAX_X 2431 | ||
71 | #define FOC_MAX_Y 1663 | ||
72 | |||
73 | /* | 70 | /* |
74 | * Current state of a single finger on the touchpad. | 71 | * Current state of a single finger on the touchpad. |
75 | */ | 72 | */ |
@@ -129,9 +126,17 @@ static void focaltech_report_state(struct psmouse *psmouse) | |||
129 | input_mt_slot(dev, i); | 126 | input_mt_slot(dev, i); |
130 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); | 127 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); |
131 | if (active) { | 128 | if (active) { |
132 | input_report_abs(dev, ABS_MT_POSITION_X, finger->x); | 129 | unsigned int clamped_x, clamped_y; |
130 | /* | ||
131 | * The touchpad might report invalid data, so we clamp | ||
132 | * the resulting values so that we do not confuse | ||
133 | * userspace. | ||
134 | */ | ||
135 | clamped_x = clamp(finger->x, 0U, priv->x_max); | ||
136 | clamped_y = clamp(finger->y, 0U, priv->y_max); | ||
137 | input_report_abs(dev, ABS_MT_POSITION_X, clamped_x); | ||
133 | input_report_abs(dev, ABS_MT_POSITION_Y, | 138 | input_report_abs(dev, ABS_MT_POSITION_Y, |
134 | FOC_MAX_Y - finger->y); | 139 | priv->y_max - clamped_y); |
135 | } | 140 | } |
136 | } | 141 | } |
137 | input_mt_report_pointer_emulation(dev, true); | 142 | input_mt_report_pointer_emulation(dev, true); |
@@ -180,16 +185,6 @@ static void focaltech_process_abs_packet(struct psmouse *psmouse, | |||
180 | 185 | ||
181 | state->pressed = (packet[0] >> 4) & 1; | 186 | state->pressed = (packet[0] >> 4) & 1; |
182 | 187 | ||
183 | /* | ||
184 | * packet[5] contains some kind of tool size in the most | ||
185 | * significant nibble. 0xff is a special value (latching) that | ||
186 | * signals a large contact area. | ||
187 | */ | ||
188 | if (packet[5] == 0xff) { | ||
189 | state->fingers[finger].valid = false; | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2]; | 188 | state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2]; |
194 | state->fingers[finger].y = (packet[3] << 8) | packet[4]; | 189 | state->fingers[finger].y = (packet[3] << 8) | packet[4]; |
195 | state->fingers[finger].valid = true; | 190 | state->fingers[finger].valid = true; |
@@ -381,6 +376,23 @@ static int focaltech_read_size(struct psmouse *psmouse) | |||
381 | 376 | ||
382 | return 0; | 377 | return 0; |
383 | } | 378 | } |
379 | |||
380 | void focaltech_set_resolution(struct psmouse *psmouse, unsigned int resolution) | ||
381 | { | ||
382 | /* not supported yet */ | ||
383 | } | ||
384 | |||
385 | static void focaltech_set_rate(struct psmouse *psmouse, unsigned int rate) | ||
386 | { | ||
387 | /* not supported yet */ | ||
388 | } | ||
389 | |||
390 | static void focaltech_set_scale(struct psmouse *psmouse, | ||
391 | enum psmouse_scale scale) | ||
392 | { | ||
393 | /* not supported yet */ | ||
394 | } | ||
395 | |||
384 | int focaltech_init(struct psmouse *psmouse) | 396 | int focaltech_init(struct psmouse *psmouse) |
385 | { | 397 | { |
386 | struct focaltech_data *priv; | 398 | struct focaltech_data *priv; |
@@ -415,6 +427,14 @@ int focaltech_init(struct psmouse *psmouse) | |||
415 | psmouse->cleanup = focaltech_reset; | 427 | psmouse->cleanup = focaltech_reset; |
416 | /* resync is not supported yet */ | 428 | /* resync is not supported yet */ |
417 | psmouse->resync_time = 0; | 429 | psmouse->resync_time = 0; |
430 | /* | ||
431 | * rate/resolution/scale changes are not supported yet, and | ||
432 | * the generic implementations of these functions seem to | ||
433 | * confuse some touchpads | ||
434 | */ | ||
435 | psmouse->set_resolution = focaltech_set_resolution; | ||
436 | psmouse->set_rate = focaltech_set_rate; | ||
437 | psmouse->set_scale = focaltech_set_scale; | ||
418 | 438 | ||
419 | return 0; | 439 | return 0; |
420 | 440 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 23222dd5a66f..e5ed216824e9 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -256,8 +256,8 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
256 | 256 | ||
257 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) | 257 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
258 | { | 258 | { |
259 | if (!lifebook_present) | 259 | if (!lifebook_present) |
260 | return -1; | 260 | return -1; |
261 | 261 | ||
262 | if (desired_serio_phys && | 262 | if (desired_serio_phys && |
263 | strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) | 263 | strcmp(psmouse->ps2dev.serio->phys, desired_serio_phys)) |
@@ -268,7 +268,7 @@ int lifebook_detect(struct psmouse *psmouse, bool set_properties) | |||
268 | psmouse->name = "Lifebook TouchScreen"; | 268 | psmouse->name = "Lifebook TouchScreen"; |
269 | } | 269 | } |
270 | 270 | ||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | 273 | ||
274 | static int lifebook_create_relative_device(struct psmouse *psmouse) | 274 | static int lifebook_create_relative_device(struct psmouse *psmouse) |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4ccd01d7a48d..27057df7ba74 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -454,6 +454,17 @@ static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate) | |||
454 | } | 454 | } |
455 | 455 | ||
456 | /* | 456 | /* |
457 | * Here we set the mouse scaling. | ||
458 | */ | ||
459 | |||
460 | static void psmouse_set_scale(struct psmouse *psmouse, enum psmouse_scale scale) | ||
461 | { | ||
462 | ps2_command(&psmouse->ps2dev, NULL, | ||
463 | scale == PSMOUSE_SCALE21 ? PSMOUSE_CMD_SETSCALE21 : | ||
464 | PSMOUSE_CMD_SETSCALE11); | ||
465 | } | ||
466 | |||
467 | /* | ||
457 | * psmouse_poll() - default poll handler. Everyone except for ALPS uses it. | 468 | * psmouse_poll() - default poll handler. Everyone except for ALPS uses it. |
458 | */ | 469 | */ |
459 | 470 | ||
@@ -463,19 +474,45 @@ static int psmouse_poll(struct psmouse *psmouse) | |||
463 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | 474 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); |
464 | } | 475 | } |
465 | 476 | ||
477 | static bool psmouse_check_pnp_id(const char *id, const char * const ids[]) | ||
478 | { | ||
479 | int i; | ||
480 | |||
481 | for (i = 0; ids[i]; i++) | ||
482 | if (!strcasecmp(id, ids[i])) | ||
483 | return true; | ||
484 | |||
485 | return false; | ||
486 | } | ||
487 | |||
466 | /* | 488 | /* |
467 | * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids. | 489 | * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids. |
468 | */ | 490 | */ |
469 | bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) | 491 | bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[]) |
470 | { | 492 | { |
471 | int i; | 493 | struct serio *serio = psmouse->ps2dev.serio; |
472 | 494 | char *p, *fw_id_copy, *save_ptr; | |
473 | if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4)) | 495 | bool found = false; |
474 | for (i = 0; ids[i]; i++) | 496 | |
475 | if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i])) | 497 | if (strncmp(serio->firmware_id, "PNP: ", 5)) |
476 | return true; | 498 | return false; |
499 | |||
500 | fw_id_copy = kstrndup(&serio->firmware_id[5], | ||
501 | sizeof(serio->firmware_id) - 5, | ||
502 | GFP_KERNEL); | ||
503 | if (!fw_id_copy) | ||
504 | return false; | ||
505 | |||
506 | save_ptr = fw_id_copy; | ||
507 | while ((p = strsep(&fw_id_copy, " ")) != NULL) { | ||
508 | if (psmouse_check_pnp_id(p, ids)) { | ||
509 | found = true; | ||
510 | break; | ||
511 | } | ||
512 | } | ||
477 | 513 | ||
478 | return false; | 514 | kfree(save_ptr); |
515 | return found; | ||
479 | } | 516 | } |
480 | 517 | ||
481 | /* | 518 | /* |
@@ -689,6 +726,7 @@ static void psmouse_apply_defaults(struct psmouse *psmouse) | |||
689 | 726 | ||
690 | psmouse->set_rate = psmouse_set_rate; | 727 | psmouse->set_rate = psmouse_set_rate; |
691 | psmouse->set_resolution = psmouse_set_resolution; | 728 | psmouse->set_resolution = psmouse_set_resolution; |
729 | psmouse->set_scale = psmouse_set_scale; | ||
692 | psmouse->poll = psmouse_poll; | 730 | psmouse->poll = psmouse_poll; |
693 | psmouse->protocol_handler = psmouse_process_byte; | 731 | psmouse->protocol_handler = psmouse_process_byte; |
694 | psmouse->pktsize = 3; | 732 | psmouse->pktsize = 3; |
@@ -1160,7 +1198,7 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
1160 | if (psmouse_max_proto != PSMOUSE_PS2) { | 1198 | if (psmouse_max_proto != PSMOUSE_PS2) { |
1161 | psmouse->set_rate(psmouse, psmouse->rate); | 1199 | psmouse->set_rate(psmouse, psmouse->rate); |
1162 | psmouse->set_resolution(psmouse, psmouse->resolution); | 1200 | psmouse->set_resolution(psmouse, psmouse->resolution); |
1163 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11); | 1201 | psmouse->set_scale(psmouse, PSMOUSE_SCALE11); |
1164 | } | 1202 | } |
1165 | } | 1203 | } |
1166 | 1204 | ||
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index c2ff137ecbdb..d02e1bdc9ae4 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -36,6 +36,11 @@ typedef enum { | |||
36 | PSMOUSE_FULL_PACKET | 36 | PSMOUSE_FULL_PACKET |
37 | } psmouse_ret_t; | 37 | } psmouse_ret_t; |
38 | 38 | ||
39 | enum psmouse_scale { | ||
40 | PSMOUSE_SCALE11, | ||
41 | PSMOUSE_SCALE21 | ||
42 | }; | ||
43 | |||
39 | struct psmouse { | 44 | struct psmouse { |
40 | void *private; | 45 | void *private; |
41 | struct input_dev *dev; | 46 | struct input_dev *dev; |
@@ -67,6 +72,7 @@ struct psmouse { | |||
67 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); | 72 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); |
68 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); | 73 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); |
69 | void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution); | 74 | void (*set_resolution)(struct psmouse *psmouse, unsigned int resolution); |
75 | void (*set_scale)(struct psmouse *psmouse, enum psmouse_scale scale); | ||
70 | 76 | ||
71 | int (*reconnect)(struct psmouse *psmouse); | 77 | int (*reconnect)(struct psmouse *psmouse); |
72 | void (*disconnect)(struct psmouse *psmouse); | 78 | void (*disconnect)(struct psmouse *psmouse); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index f2cceb6493a0..630af73e98c4 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -123,32 +123,46 @@ void synaptics_reset(struct psmouse *psmouse) | |||
123 | 123 | ||
124 | static bool cr48_profile_sensor; | 124 | static bool cr48_profile_sensor; |
125 | 125 | ||
126 | #define ANY_BOARD_ID 0 | ||
126 | struct min_max_quirk { | 127 | struct min_max_quirk { |
127 | const char * const *pnp_ids; | 128 | const char * const *pnp_ids; |
129 | struct { | ||
130 | unsigned long int min, max; | ||
131 | } board_id; | ||
128 | int x_min, x_max, y_min, y_max; | 132 | int x_min, x_max, y_min, y_max; |
129 | }; | 133 | }; |
130 | 134 | ||
131 | static const struct min_max_quirk min_max_pnpid_table[] = { | 135 | static const struct min_max_quirk min_max_pnpid_table[] = { |
132 | { | 136 | { |
133 | (const char * const []){"LEN0033", NULL}, | 137 | (const char * const []){"LEN0033", NULL}, |
138 | {ANY_BOARD_ID, ANY_BOARD_ID}, | ||
134 | 1024, 5052, 2258, 4832 | 139 | 1024, 5052, 2258, 4832 |
135 | }, | 140 | }, |
136 | { | 141 | { |
137 | (const char * const []){"LEN0035", "LEN0042", NULL}, | 142 | (const char * const []){"LEN0042", NULL}, |
143 | {ANY_BOARD_ID, ANY_BOARD_ID}, | ||
138 | 1232, 5710, 1156, 4696 | 144 | 1232, 5710, 1156, 4696 |
139 | }, | 145 | }, |
140 | { | 146 | { |
141 | (const char * const []){"LEN0034", "LEN0036", "LEN0037", | 147 | (const char * const []){"LEN0034", "LEN0036", "LEN0037", |
142 | "LEN0039", "LEN2002", "LEN2004", | 148 | "LEN0039", "LEN2002", "LEN2004", |
143 | NULL}, | 149 | NULL}, |
150 | {ANY_BOARD_ID, 2961}, | ||
144 | 1024, 5112, 2024, 4832 | 151 | 1024, 5112, 2024, 4832 |
145 | }, | 152 | }, |
146 | { | 153 | { |
147 | (const char * const []){"LEN2001", NULL}, | 154 | (const char * const []){"LEN2001", NULL}, |
155 | {ANY_BOARD_ID, ANY_BOARD_ID}, | ||
148 | 1024, 5022, 2508, 4832 | 156 | 1024, 5022, 2508, 4832 |
149 | }, | 157 | }, |
150 | { | 158 | { |
151 | (const char * const []){"LEN2006", NULL}, | 159 | (const char * const []){"LEN2006", NULL}, |
160 | {2691, 2691}, | ||
161 | 1024, 5045, 2457, 4832 | ||
162 | }, | ||
163 | { | ||
164 | (const char * const []){"LEN2006", NULL}, | ||
165 | {ANY_BOARD_ID, ANY_BOARD_ID}, | ||
152 | 1264, 5675, 1171, 4688 | 166 | 1264, 5675, 1171, 4688 |
153 | }, | 167 | }, |
154 | { } | 168 | { } |
@@ -175,9 +189,7 @@ static const char * const topbuttonpad_pnp_ids[] = { | |||
175 | "LEN0041", | 189 | "LEN0041", |
176 | "LEN0042", /* Yoga */ | 190 | "LEN0042", /* Yoga */ |
177 | "LEN0045", | 191 | "LEN0045", |
178 | "LEN0046", | ||
179 | "LEN0047", | 192 | "LEN0047", |
180 | "LEN0048", | ||
181 | "LEN0049", | 193 | "LEN0049", |
182 | "LEN2000", | 194 | "LEN2000", |
183 | "LEN2001", /* Edge E431 */ | 195 | "LEN2001", /* Edge E431 */ |
@@ -185,7 +197,7 @@ static const char * const topbuttonpad_pnp_ids[] = { | |||
185 | "LEN2003", | 197 | "LEN2003", |
186 | "LEN2004", /* L440 */ | 198 | "LEN2004", /* L440 */ |
187 | "LEN2005", | 199 | "LEN2005", |
188 | "LEN2006", | 200 | "LEN2006", /* Edge E440/E540 */ |
189 | "LEN2007", | 201 | "LEN2007", |
190 | "LEN2008", | 202 | "LEN2008", |
191 | "LEN2009", | 203 | "LEN2009", |
@@ -194,6 +206,13 @@ static const char * const topbuttonpad_pnp_ids[] = { | |||
194 | NULL | 206 | NULL |
195 | }; | 207 | }; |
196 | 208 | ||
209 | /* This list has been kindly provided by Synaptics. */ | ||
210 | static const char * const forcepad_pnp_ids[] = { | ||
211 | "SYN300D", | ||
212 | "SYN3014", | ||
213 | NULL | ||
214 | }; | ||
215 | |||
197 | /***************************************************************************** | 216 | /***************************************************************************** |
198 | * Synaptics communications functions | 217 | * Synaptics communications functions |
199 | ****************************************************************************/ | 218 | ****************************************************************************/ |
@@ -235,18 +254,39 @@ static int synaptics_model_id(struct psmouse *psmouse) | |||
235 | return 0; | 254 | return 0; |
236 | } | 255 | } |
237 | 256 | ||
257 | static int synaptics_more_extended_queries(struct psmouse *psmouse) | ||
258 | { | ||
259 | struct synaptics_data *priv = psmouse->private; | ||
260 | unsigned char buf[3]; | ||
261 | |||
262 | if (synaptics_send_cmd(psmouse, SYN_QUE_MEXT_CAPAB_10, buf)) | ||
263 | return -1; | ||
264 | |||
265 | priv->ext_cap_10 = (buf[0]<<16) | (buf[1]<<8) | buf[2]; | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
238 | /* | 270 | /* |
239 | * Read the board id from the touchpad | 271 | * Read the board id and the "More Extended Queries" from the touchpad |
240 | * The board id is encoded in the "QUERY MODES" response | 272 | * The board id is encoded in the "QUERY MODES" response |
241 | */ | 273 | */ |
242 | static int synaptics_board_id(struct psmouse *psmouse) | 274 | static int synaptics_query_modes(struct psmouse *psmouse) |
243 | { | 275 | { |
244 | struct synaptics_data *priv = psmouse->private; | 276 | struct synaptics_data *priv = psmouse->private; |
245 | unsigned char bid[3]; | 277 | unsigned char bid[3]; |
246 | 278 | ||
279 | /* firmwares prior 7.5 have no board_id encoded */ | ||
280 | if (SYN_ID_FULL(priv->identity) < 0x705) | ||
281 | return 0; | ||
282 | |||
247 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) | 283 | if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) |
248 | return -1; | 284 | return -1; |
249 | priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; | 285 | priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; |
286 | |||
287 | if (SYN_MEXT_CAP_BIT(bid[0])) | ||
288 | return synaptics_more_extended_queries(psmouse); | ||
289 | |||
250 | return 0; | 290 | return 0; |
251 | } | 291 | } |
252 | 292 | ||
@@ -346,7 +386,6 @@ static int synaptics_resolution(struct psmouse *psmouse) | |||
346 | { | 386 | { |
347 | struct synaptics_data *priv = psmouse->private; | 387 | struct synaptics_data *priv = psmouse->private; |
348 | unsigned char resp[3]; | 388 | unsigned char resp[3]; |
349 | int i; | ||
350 | 389 | ||
351 | if (SYN_ID_MAJOR(priv->identity) < 4) | 390 | if (SYN_ID_MAJOR(priv->identity) < 4) |
352 | return 0; | 391 | return 0; |
@@ -358,17 +397,6 @@ static int synaptics_resolution(struct psmouse *psmouse) | |||
358 | } | 397 | } |
359 | } | 398 | } |
360 | 399 | ||
361 | for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { | ||
362 | if (psmouse_matches_pnp_id(psmouse, | ||
363 | min_max_pnpid_table[i].pnp_ids)) { | ||
364 | priv->x_min = min_max_pnpid_table[i].x_min; | ||
365 | priv->x_max = min_max_pnpid_table[i].x_max; | ||
366 | priv->y_min = min_max_pnpid_table[i].y_min; | ||
367 | priv->y_max = min_max_pnpid_table[i].y_max; | ||
368 | return 0; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && | 400 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && |
373 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { | 401 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { |
374 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { | 402 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { |
@@ -377,23 +405,69 @@ static int synaptics_resolution(struct psmouse *psmouse) | |||
377 | } else { | 405 | } else { |
378 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 406 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
379 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 407 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
408 | psmouse_info(psmouse, | ||
409 | "queried max coordinates: x [..%d], y [..%d]\n", | ||
410 | priv->x_max, priv->y_max); | ||
380 | } | 411 | } |
381 | } | 412 | } |
382 | 413 | ||
383 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && | 414 | if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) && |
384 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { | 415 | (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 || |
416 | /* | ||
417 | * Firmware v8.1 does not report proper number of extended | ||
418 | * capabilities, but has been proven to report correct min | ||
419 | * coordinates. | ||
420 | */ | ||
421 | SYN_ID_FULL(priv->identity) == 0x801)) { | ||
385 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { | 422 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { |
386 | psmouse_warn(psmouse, | 423 | psmouse_warn(psmouse, |
387 | "device claims to have min coordinates query, but I'm not able to read it.\n"); | 424 | "device claims to have min coordinates query, but I'm not able to read it.\n"); |
388 | } else { | 425 | } else { |
389 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | 426 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
390 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | 427 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
428 | psmouse_info(psmouse, | ||
429 | "queried min coordinates: x [%d..], y [%d..]\n", | ||
430 | priv->x_min, priv->y_min); | ||
391 | } | 431 | } |
392 | } | 432 | } |
393 | 433 | ||
394 | return 0; | 434 | return 0; |
395 | } | 435 | } |
396 | 436 | ||
437 | /* | ||
438 | * Apply quirk(s) if the hardware matches | ||
439 | */ | ||
440 | |||
441 | static void synaptics_apply_quirks(struct psmouse *psmouse) | ||
442 | { | ||
443 | struct synaptics_data *priv = psmouse->private; | ||
444 | int i; | ||
445 | |||
446 | for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { | ||
447 | if (!psmouse_matches_pnp_id(psmouse, | ||
448 | min_max_pnpid_table[i].pnp_ids)) | ||
449 | continue; | ||
450 | |||
451 | if (min_max_pnpid_table[i].board_id.min != ANY_BOARD_ID && | ||
452 | priv->board_id < min_max_pnpid_table[i].board_id.min) | ||
453 | continue; | ||
454 | |||
455 | if (min_max_pnpid_table[i].board_id.max != ANY_BOARD_ID && | ||
456 | priv->board_id > min_max_pnpid_table[i].board_id.max) | ||
457 | continue; | ||
458 | |||
459 | priv->x_min = min_max_pnpid_table[i].x_min; | ||
460 | priv->x_max = min_max_pnpid_table[i].x_max; | ||
461 | priv->y_min = min_max_pnpid_table[i].y_min; | ||
462 | priv->y_max = min_max_pnpid_table[i].y_max; | ||
463 | psmouse_info(psmouse, | ||
464 | "quirked min/max coordinates: x [%d..%d], y [%d..%d]\n", | ||
465 | priv->x_min, priv->x_max, | ||
466 | priv->y_min, priv->y_max); | ||
467 | break; | ||
468 | } | ||
469 | } | ||
470 | |||
397 | static int synaptics_query_hardware(struct psmouse *psmouse) | 471 | static int synaptics_query_hardware(struct psmouse *psmouse) |
398 | { | 472 | { |
399 | if (synaptics_identify(psmouse)) | 473 | if (synaptics_identify(psmouse)) |
@@ -402,13 +476,15 @@ static int synaptics_query_hardware(struct psmouse *psmouse) | |||
402 | return -1; | 476 | return -1; |
403 | if (synaptics_firmware_id(psmouse)) | 477 | if (synaptics_firmware_id(psmouse)) |
404 | return -1; | 478 | return -1; |
405 | if (synaptics_board_id(psmouse)) | 479 | if (synaptics_query_modes(psmouse)) |
406 | return -1; | 480 | return -1; |
407 | if (synaptics_capability(psmouse)) | 481 | if (synaptics_capability(psmouse)) |
408 | return -1; | 482 | return -1; |
409 | if (synaptics_resolution(psmouse)) | 483 | if (synaptics_resolution(psmouse)) |
410 | return -1; | 484 | return -1; |
411 | 485 | ||
486 | synaptics_apply_quirks(psmouse); | ||
487 | |||
412 | return 0; | 488 | return 0; |
413 | } | 489 | } |
414 | 490 | ||
@@ -516,18 +592,22 @@ static int synaptics_is_pt_packet(unsigned char *buf) | |||
516 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; | 592 | return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; |
517 | } | 593 | } |
518 | 594 | ||
519 | static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) | 595 | static void synaptics_pass_pt_packet(struct psmouse *psmouse, |
596 | struct serio *ptport, | ||
597 | unsigned char *packet) | ||
520 | { | 598 | { |
599 | struct synaptics_data *priv = psmouse->private; | ||
521 | struct psmouse *child = serio_get_drvdata(ptport); | 600 | struct psmouse *child = serio_get_drvdata(ptport); |
522 | 601 | ||
523 | if (child && child->state == PSMOUSE_ACTIVATED) { | 602 | if (child && child->state == PSMOUSE_ACTIVATED) { |
524 | serio_interrupt(ptport, packet[1], 0); | 603 | serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0); |
525 | serio_interrupt(ptport, packet[4], 0); | 604 | serio_interrupt(ptport, packet[4], 0); |
526 | serio_interrupt(ptport, packet[5], 0); | 605 | serio_interrupt(ptport, packet[5], 0); |
527 | if (child->pktsize == 4) | 606 | if (child->pktsize == 4) |
528 | serio_interrupt(ptport, packet[2], 0); | 607 | serio_interrupt(ptport, packet[2], 0); |
529 | } else | 608 | } else { |
530 | serio_interrupt(ptport, packet[1], 0); | 609 | serio_interrupt(ptport, packet[1], 0); |
610 | } | ||
531 | } | 611 | } |
532 | 612 | ||
533 | static void synaptics_pt_activate(struct psmouse *psmouse) | 613 | static void synaptics_pt_activate(struct psmouse *psmouse) |
@@ -605,7 +685,17 @@ static void synaptics_parse_agm(const unsigned char buf[], | |||
605 | } | 685 | } |
606 | } | 686 | } |
607 | 687 | ||
608 | static bool is_forcepad; | 688 | static void synaptics_parse_ext_buttons(const unsigned char buf[], |
689 | struct synaptics_data *priv, | ||
690 | struct synaptics_hw_state *hw) | ||
691 | { | ||
692 | unsigned int ext_bits = | ||
693 | (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; | ||
694 | unsigned int ext_mask = GENMASK(ext_bits - 1, 0); | ||
695 | |||
696 | hw->ext_buttons = buf[4] & ext_mask; | ||
697 | hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits; | ||
698 | } | ||
609 | 699 | ||
610 | static int synaptics_parse_hw_state(const unsigned char buf[], | 700 | static int synaptics_parse_hw_state(const unsigned char buf[], |
611 | struct synaptics_data *priv, | 701 | struct synaptics_data *priv, |
@@ -636,7 +726,7 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
636 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 726 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
637 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 727 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
638 | 728 | ||
639 | if (is_forcepad) { | 729 | if (priv->is_forcepad) { |
640 | /* | 730 | /* |
641 | * ForcePads, like Clickpads, use middle button | 731 | * ForcePads, like Clickpads, use middle button |
642 | * bits to report primary button clicks. | 732 | * bits to report primary button clicks. |
@@ -691,28 +781,9 @@ static int synaptics_parse_hw_state(const unsigned char buf[], | |||
691 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; | 781 | hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; |
692 | } | 782 | } |
693 | 783 | ||
694 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && | 784 | if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 && |
695 | ((buf[0] ^ buf[3]) & 0x02)) { | 785 | ((buf[0] ^ buf[3]) & 0x02)) { |
696 | switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { | 786 | synaptics_parse_ext_buttons(buf, priv, hw); |
697 | default: | ||
698 | /* | ||
699 | * if nExtBtn is greater than 8 it should be | ||
700 | * considered invalid and treated as 0 | ||
701 | */ | ||
702 | break; | ||
703 | case 8: | ||
704 | hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; | ||
705 | hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; | ||
706 | case 6: | ||
707 | hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; | ||
708 | hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; | ||
709 | case 4: | ||
710 | hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; | ||
711 | hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; | ||
712 | case 2: | ||
713 | hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; | ||
714 | hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; | ||
715 | } | ||
716 | } | 787 | } |
717 | } else { | 788 | } else { |
718 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); | 789 | hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); |
@@ -774,12 +845,54 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev, | |||
774 | } | 845 | } |
775 | } | 846 | } |
776 | 847 | ||
848 | static void synaptics_report_ext_buttons(struct psmouse *psmouse, | ||
849 | const struct synaptics_hw_state *hw) | ||
850 | { | ||
851 | struct input_dev *dev = psmouse->dev; | ||
852 | struct synaptics_data *priv = psmouse->private; | ||
853 | int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; | ||
854 | char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
855 | int i; | ||
856 | |||
857 | if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) | ||
858 | return; | ||
859 | |||
860 | /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */ | ||
861 | if (SYN_ID_FULL(priv->identity) == 0x801 && | ||
862 | !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) | ||
863 | return; | ||
864 | |||
865 | if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) { | ||
866 | for (i = 0; i < ext_bits; i++) { | ||
867 | input_report_key(dev, BTN_0 + 2 * i, | ||
868 | hw->ext_buttons & (1 << i)); | ||
869 | input_report_key(dev, BTN_1 + 2 * i, | ||
870 | hw->ext_buttons & (1 << (i + ext_bits))); | ||
871 | } | ||
872 | return; | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * This generation of touchpads has the trackstick buttons | ||
877 | * physically wired to the touchpad. Re-route them through | ||
878 | * the pass-through interface. | ||
879 | */ | ||
880 | if (!priv->pt_port) | ||
881 | return; | ||
882 | |||
883 | /* The trackstick expects at most 3 buttons */ | ||
884 | priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons) | | ||
885 | SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 | | ||
886 | SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2; | ||
887 | |||
888 | synaptics_pass_pt_packet(psmouse, priv->pt_port, buf); | ||
889 | } | ||
890 | |||
777 | static void synaptics_report_buttons(struct psmouse *psmouse, | 891 | static void synaptics_report_buttons(struct psmouse *psmouse, |
778 | const struct synaptics_hw_state *hw) | 892 | const struct synaptics_hw_state *hw) |
779 | { | 893 | { |
780 | struct input_dev *dev = psmouse->dev; | 894 | struct input_dev *dev = psmouse->dev; |
781 | struct synaptics_data *priv = psmouse->private; | 895 | struct synaptics_data *priv = psmouse->private; |
782 | int i; | ||
783 | 896 | ||
784 | input_report_key(dev, BTN_LEFT, hw->left); | 897 | input_report_key(dev, BTN_LEFT, hw->left); |
785 | input_report_key(dev, BTN_RIGHT, hw->right); | 898 | input_report_key(dev, BTN_RIGHT, hw->right); |
@@ -792,8 +905,7 @@ static void synaptics_report_buttons(struct psmouse *psmouse, | |||
792 | input_report_key(dev, BTN_BACK, hw->down); | 905 | input_report_key(dev, BTN_BACK, hw->down); |
793 | } | 906 | } |
794 | 907 | ||
795 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 908 | synaptics_report_ext_buttons(psmouse, hw); |
796 | input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); | ||
797 | } | 909 | } |
798 | 910 | ||
799 | static void synaptics_report_mt_data(struct psmouse *psmouse, | 911 | static void synaptics_report_mt_data(struct psmouse *psmouse, |
@@ -1014,7 +1126,8 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) | |||
1014 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && | 1126 | if (SYN_CAP_PASS_THROUGH(priv->capabilities) && |
1015 | synaptics_is_pt_packet(psmouse->packet)) { | 1127 | synaptics_is_pt_packet(psmouse->packet)) { |
1016 | if (priv->pt_port) | 1128 | if (priv->pt_port) |
1017 | synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); | 1129 | synaptics_pass_pt_packet(psmouse, priv->pt_port, |
1130 | psmouse->packet); | ||
1018 | } else | 1131 | } else |
1019 | synaptics_process_packet(psmouse); | 1132 | synaptics_process_packet(psmouse); |
1020 | 1133 | ||
@@ -1081,7 +1194,7 @@ static void set_input_params(struct psmouse *psmouse, | |||
1081 | ABS_MT_POSITION_Y); | 1194 | ABS_MT_POSITION_Y); |
1082 | /* Image sensors can report per-contact pressure */ | 1195 | /* Image sensors can report per-contact pressure */ |
1083 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | 1196 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); |
1084 | input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK); | 1197 | input_mt_init_slots(dev, 3, INPUT_MT_POINTER | INPUT_MT_TRACK); |
1085 | 1198 | ||
1086 | /* Image sensors can signal 4 and 5 finger clicks */ | 1199 | /* Image sensors can signal 4 and 5 finger clicks */ |
1087 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1200 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
@@ -1116,8 +1229,9 @@ static void set_input_params(struct psmouse *psmouse, | |||
1116 | __set_bit(BTN_BACK, dev->keybit); | 1229 | __set_bit(BTN_BACK, dev->keybit); |
1117 | } | 1230 | } |
1118 | 1231 | ||
1119 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 1232 | if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) |
1120 | __set_bit(BTN_0 + i, dev->keybit); | 1233 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
1234 | __set_bit(BTN_0 + i, dev->keybit); | ||
1121 | 1235 | ||
1122 | __clear_bit(EV_REL, dev->evbit); | 1236 | __clear_bit(EV_REL, dev->evbit); |
1123 | __clear_bit(REL_X, dev->relbit); | 1237 | __clear_bit(REL_X, dev->relbit); |
@@ -1125,7 +1239,8 @@ static void set_input_params(struct psmouse *psmouse, | |||
1125 | 1239 | ||
1126 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | 1240 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
1127 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); | 1241 | __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); |
1128 | if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) | 1242 | if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && |
1243 | !SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) | ||
1129 | __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); | 1244 | __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); |
1130 | /* Clickpads report only left button */ | 1245 | /* Clickpads report only left button */ |
1131 | __clear_bit(BTN_RIGHT, dev->keybit); | 1246 | __clear_bit(BTN_RIGHT, dev->keybit); |
@@ -1311,29 +1426,11 @@ static const struct dmi_system_id __initconst cr48_dmi_table[] = { | |||
1311 | { } | 1426 | { } |
1312 | }; | 1427 | }; |
1313 | 1428 | ||
1314 | static const struct dmi_system_id forcepad_dmi_table[] __initconst = { | ||
1315 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
1316 | { | ||
1317 | .matches = { | ||
1318 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1319 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"), | ||
1320 | }, | ||
1321 | }, | ||
1322 | #endif | ||
1323 | { } | ||
1324 | }; | ||
1325 | |||
1326 | void __init synaptics_module_init(void) | 1429 | void __init synaptics_module_init(void) |
1327 | { | 1430 | { |
1328 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | 1431 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
1329 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); | 1432 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
1330 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); | 1433 | cr48_profile_sensor = dmi_check_system(cr48_dmi_table); |
1331 | |||
1332 | /* | ||
1333 | * Unfortunately ForcePad capability is not exported over PS/2, | ||
1334 | * so we have to resort to checking DMI. | ||
1335 | */ | ||
1336 | is_forcepad = dmi_check_system(forcepad_dmi_table); | ||
1337 | } | 1434 | } |
1338 | 1435 | ||
1339 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | 1436 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
@@ -1368,6 +1465,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) | |||
1368 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) | 1465 | if (SYN_ID_DISGEST_SUPPORTED(priv->identity)) |
1369 | priv->disable_gesture = true; | 1466 | priv->disable_gesture = true; |
1370 | 1467 | ||
1468 | /* | ||
1469 | * Unfortunately ForcePad capability is not exported over PS/2, | ||
1470 | * so we have to resort to checking PNP IDs. | ||
1471 | */ | ||
1472 | priv->is_forcepad = psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids); | ||
1473 | |||
1371 | if (synaptics_set_mode(psmouse)) { | 1474 | if (synaptics_set_mode(psmouse)) { |
1372 | psmouse_err(psmouse, "Unable to initialize device.\n"); | 1475 | psmouse_err(psmouse, "Unable to initialize device.\n"); |
1373 | goto init_fail; | 1476 | goto init_fail; |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index aedc3299b14e..56faa7ec4434 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define SYN_QUE_EXT_CAPAB_0C 0x0c | 22 | #define SYN_QUE_EXT_CAPAB_0C 0x0c |
23 | #define SYN_QUE_EXT_MAX_COORDS 0x0d | 23 | #define SYN_QUE_EXT_MAX_COORDS 0x0d |
24 | #define SYN_QUE_EXT_MIN_COORDS 0x0f | 24 | #define SYN_QUE_EXT_MIN_COORDS 0x0f |
25 | #define SYN_QUE_MEXT_CAPAB_10 0x10 | ||
25 | 26 | ||
26 | /* synatics modes */ | 27 | /* synatics modes */ |
27 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) | 28 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) |
@@ -53,6 +54,7 @@ | |||
53 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) | 54 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) |
54 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) | 55 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) |
55 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) | 56 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) |
57 | #define SYN_MEXT_CAP_BIT(m) ((m) & (1 << 1)) | ||
56 | 58 | ||
57 | /* | 59 | /* |
58 | * The following describes response for the 0x0c query. | 60 | * The following describes response for the 0x0c query. |
@@ -89,6 +91,30 @@ | |||
89 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 91 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
90 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) | 92 | #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) |
91 | 93 | ||
94 | /* | ||
95 | * The following descibes response for the 0x10 query. | ||
96 | * | ||
97 | * byte mask name meaning | ||
98 | * ---- ---- ------- ------------ | ||
99 | * 1 0x01 ext buttons are stick buttons exported in the extended | ||
100 | * capability are actually meant to be used | ||
101 | * by the tracktick (pass-through). | ||
102 | * 1 0x02 SecurePad the touchpad is a SecurePad, so it | ||
103 | * contains a built-in fingerprint reader. | ||
104 | * 1 0xe0 more ext count how many more extented queries are | ||
105 | * available after this one. | ||
106 | * 2 0xff SecurePad width the width of the SecurePad fingerprint | ||
107 | * reader. | ||
108 | * 3 0xff SecurePad height the height of the SecurePad fingerprint | ||
109 | * reader. | ||
110 | */ | ||
111 | #define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & 0x010000) | ||
112 | #define SYN_CAP_SECUREPAD(ex10) ((ex10) & 0x020000) | ||
113 | |||
114 | #define SYN_CAP_EXT_BUTTON_STICK_L(eb) (!!((eb) & 0x01)) | ||
115 | #define SYN_CAP_EXT_BUTTON_STICK_M(eb) (!!((eb) & 0x02)) | ||
116 | #define SYN_CAP_EXT_BUTTON_STICK_R(eb) (!!((eb) & 0x04)) | ||
117 | |||
92 | /* synaptics modes query bits */ | 118 | /* synaptics modes query bits */ |
93 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 119 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
94 | #define SYN_MODE_RATE(m) ((m) & (1 << 6)) | 120 | #define SYN_MODE_RATE(m) ((m) & (1 << 6)) |
@@ -143,6 +169,7 @@ struct synaptics_data { | |||
143 | unsigned long int capabilities; /* Capabilities */ | 169 | unsigned long int capabilities; /* Capabilities */ |
144 | unsigned long int ext_cap; /* Extended Capabilities */ | 170 | unsigned long int ext_cap; /* Extended Capabilities */ |
145 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ | 171 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ |
172 | unsigned long int ext_cap_10; /* Ext Caps from 0x10 query */ | ||
146 | unsigned long int identity; /* Identification */ | 173 | unsigned long int identity; /* Identification */ |
147 | unsigned int x_res, y_res; /* X/Y resolution in units/mm */ | 174 | unsigned int x_res, y_res; /* X/Y resolution in units/mm */ |
148 | unsigned int x_max, y_max; /* Max coordinates (from FW) */ | 175 | unsigned int x_max, y_max; /* Max coordinates (from FW) */ |
@@ -156,6 +183,7 @@ struct synaptics_data { | |||
156 | bool disable_gesture; /* disable gestures */ | 183 | bool disable_gesture; /* disable gestures */ |
157 | 184 | ||
158 | struct serio *pt_port; /* Pass-through serio port */ | 185 | struct serio *pt_port; /* Pass-through serio port */ |
186 | unsigned char pt_buttons; /* Pass-through buttons */ | ||
159 | 187 | ||
160 | /* | 188 | /* |
161 | * Last received Advanced Gesture Mode (AGM) packet. An AGM packet | 189 | * Last received Advanced Gesture Mode (AGM) packet. An AGM packet |
@@ -168,6 +196,7 @@ struct synaptics_data { | |||
168 | unsigned long press_start; | 196 | unsigned long press_start; |
169 | bool press; | 197 | bool press; |
170 | bool report_press; | 198 | bool report_press; |
199 | bool is_forcepad; | ||
171 | }; | 200 | }; |
172 | 201 | ||
173 | void synaptics_module_init(void); | 202 | void synaptics_module_init(void); |
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 94ab494a6ade..ecba666afadb 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/ioport.h> | 33 | #include <linux/ioport.h> |
34 | #include <linux/pci_ids.h> | ||
35 | 34 | ||
36 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
37 | #include <asm/io.h> | 36 | #include <asm/io.h> |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 986a71c614b0..cb5ece77fd7d 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -1162,13 +1162,32 @@ static int i8042_controller_resume(bool force_reset) | |||
1162 | 1162 | ||
1163 | static int i8042_pm_suspend(struct device *dev) | 1163 | static int i8042_pm_suspend(struct device *dev) |
1164 | { | 1164 | { |
1165 | int i; | ||
1166 | |||
1165 | i8042_controller_reset(true); | 1167 | i8042_controller_reset(true); |
1166 | 1168 | ||
1169 | /* Set up serio interrupts for system wakeup. */ | ||
1170 | for (i = 0; i < I8042_NUM_PORTS; i++) { | ||
1171 | struct serio *serio = i8042_ports[i].serio; | ||
1172 | |||
1173 | if (serio && device_may_wakeup(&serio->dev)) | ||
1174 | enable_irq_wake(i8042_ports[i].irq); | ||
1175 | } | ||
1176 | |||
1167 | return 0; | 1177 | return 0; |
1168 | } | 1178 | } |
1169 | 1179 | ||
1170 | static int i8042_pm_resume(struct device *dev) | 1180 | static int i8042_pm_resume(struct device *dev) |
1171 | { | 1181 | { |
1182 | int i; | ||
1183 | |||
1184 | for (i = 0; i < I8042_NUM_PORTS; i++) { | ||
1185 | struct serio *serio = i8042_ports[i].serio; | ||
1186 | |||
1187 | if (serio && device_may_wakeup(&serio->dev)) | ||
1188 | disable_irq_wake(i8042_ports[i].irq); | ||
1189 | } | ||
1190 | |||
1172 | /* | 1191 | /* |
1173 | * On resume from S2R we always try to reset the controller | 1192 | * On resume from S2R we always try to reset the controller |
1174 | * to bring it in a sane state. (In case of S2D we expect | 1193 | * to bring it in a sane state. (In case of S2D we expect |
@@ -1300,13 +1319,16 @@ static void __init i8042_register_ports(void) | |||
1300 | int i; | 1319 | int i; |
1301 | 1320 | ||
1302 | for (i = 0; i < I8042_NUM_PORTS; i++) { | 1321 | for (i = 0; i < I8042_NUM_PORTS; i++) { |
1303 | if (i8042_ports[i].serio) { | 1322 | struct serio *serio = i8042_ports[i].serio; |
1323 | |||
1324 | if (serio) { | ||
1304 | printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", | 1325 | printk(KERN_INFO "serio: %s at %#lx,%#lx irq %d\n", |
1305 | i8042_ports[i].serio->name, | 1326 | serio->name, |
1306 | (unsigned long) I8042_DATA_REG, | 1327 | (unsigned long) I8042_DATA_REG, |
1307 | (unsigned long) I8042_COMMAND_REG, | 1328 | (unsigned long) I8042_COMMAND_REG, |
1308 | i8042_ports[i].irq); | 1329 | i8042_ports[i].irq); |
1309 | serio_register_port(i8042_ports[i].serio); | 1330 | serio_register_port(serio); |
1331 | device_set_wakeup_capable(&serio->dev, true); | ||
1310 | } | 1332 | } |
1311 | } | 1333 | } |
1312 | } | 1334 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f8d16f15c1d1..80f6386709bf 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -140,6 +140,19 @@ config TOUCHSCREEN_BU21013 | |||
140 | To compile this driver as a module, choose M here: the | 140 | To compile this driver as a module, choose M here: the |
141 | module will be called bu21013_ts. | 141 | module will be called bu21013_ts. |
142 | 142 | ||
143 | config TOUCHSCREEN_CHIPONE_ICN8318 | ||
144 | tristate "chipone icn8318 touchscreen controller" | ||
145 | depends on GPIOLIB | ||
146 | depends on I2C | ||
147 | depends on OF | ||
148 | help | ||
149 | Say Y here if you have a ChipOne icn8318 based I2C touchscreen. | ||
150 | |||
151 | If unsure, say N. | ||
152 | |||
153 | To compile this driver as a module, choose M here: the | ||
154 | module will be called chipone_icn8318. | ||
155 | |||
143 | config TOUCHSCREEN_CY8CTMG110 | 156 | config TOUCHSCREEN_CY8CTMG110 |
144 | tristate "cy8ctmg110 touchscreen" | 157 | tristate "cy8ctmg110 touchscreen" |
145 | depends on I2C | 158 | depends on I2C |
@@ -297,11 +310,12 @@ config TOUCHSCREEN_FUJITSU | |||
297 | 310 | ||
298 | config TOUCHSCREEN_GOODIX | 311 | config TOUCHSCREEN_GOODIX |
299 | tristate "Goodix I2C touchscreen" | 312 | tristate "Goodix I2C touchscreen" |
300 | depends on I2C && ACPI | 313 | depends on I2C |
301 | help | 314 | help |
302 | Say Y here if you have the Goodix touchscreen (such as one | 315 | Say Y here if you have the Goodix touchscreen (such as one |
303 | installed in Onda v975w tablets) connected to your | 316 | installed in Onda v975w tablets) connected to your |
304 | system. | 317 | system. It also supports 5-finger chip models, which can be |
318 | found on ARM tablets, like Wexler TAB7200 and MSI Primo73. | ||
305 | 319 | ||
306 | If unsure, say N. | 320 | If unsure, say N. |
307 | 321 | ||
@@ -323,6 +337,18 @@ config TOUCHSCREEN_ILI210X | |||
323 | To compile this driver as a module, choose M here: the | 337 | To compile this driver as a module, choose M here: the |
324 | module will be called ili210x. | 338 | module will be called ili210x. |
325 | 339 | ||
340 | config TOUCHSCREEN_IPROC | ||
341 | tristate "IPROC touch panel driver support" | ||
342 | depends on ARCH_BCM_IPROC || COMPILE_TEST | ||
343 | help | ||
344 | Say Y here if you want to add support for the IPROC touch | ||
345 | controller to your system. | ||
346 | |||
347 | If unsure, say N. | ||
348 | |||
349 | To compile this driver as a module, choose M here: the | ||
350 | module will be called bcm_iproc_tsc. | ||
351 | |||
326 | config TOUCHSCREEN_S3C2410 | 352 | config TOUCHSCREEN_S3C2410 |
327 | tristate "Samsung S3C2410/generic touchscreen input driver" | 353 | tristate "Samsung S3C2410/generic touchscreen input driver" |
328 | depends on ARCH_S3C24XX || SAMSUNG_DEV_TS | 354 | depends on ARCH_S3C24XX || SAMSUNG_DEV_TS |
@@ -943,6 +969,7 @@ config TOUCHSCREEN_SUN4I | |||
943 | tristate "Allwinner sun4i resistive touchscreen controller support" | 969 | tristate "Allwinner sun4i resistive touchscreen controller support" |
944 | depends on ARCH_SUNXI || COMPILE_TEST | 970 | depends on ARCH_SUNXI || COMPILE_TEST |
945 | depends on HWMON | 971 | depends on HWMON |
972 | depends on THERMAL || !THERMAL_OF | ||
946 | help | 973 | help |
947 | This selects support for the resistive touchscreen controller | 974 | This selects support for the resistive touchscreen controller |
948 | found on Allwinner sunxi SoCs. | 975 | found on Allwinner sunxi SoCs. |
@@ -963,6 +990,17 @@ config TOUCHSCREEN_SUR40 | |||
963 | To compile this driver as a module, choose M here: the | 990 | To compile this driver as a module, choose M here: the |
964 | module will be called sur40. | 991 | module will be called sur40. |
965 | 992 | ||
993 | config TOUCHSCREEN_SX8654 | ||
994 | tristate "Semtech SX8654 touchscreen" | ||
995 | depends on I2C | ||
996 | help | ||
997 | Say Y here if you have a Semtech SX8654 touchscreen controller. | ||
998 | |||
999 | If unsure, say N | ||
1000 | |||
1001 | To compile this driver as a module, choose M here: the | ||
1002 | module will be called sx8654. | ||
1003 | |||
966 | config TOUCHSCREEN_TPS6507X | 1004 | config TOUCHSCREEN_TPS6507X |
967 | tristate "TPS6507x based touchscreens" | 1005 | tristate "TPS6507x based touchscreens" |
968 | depends on I2C | 1006 | depends on I2C |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 0242fea2102a..44deea743d02 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o | |||
17 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o |
18 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o | 19 | obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o |
20 | obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o | ||
20 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o | 21 | obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o |
22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o | 23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o |
@@ -39,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o | |||
39 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o | 40 | obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o |
40 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 41 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
41 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o | 42 | obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o |
43 | obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o | ||
42 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o | 44 | obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o |
43 | obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o | 45 | obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o |
44 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o | 46 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o |
@@ -79,5 +81,6 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
79 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 81 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
80 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 82 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
81 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 83 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
84 | obj-$(CONFIG_TOUCHSCREEN_SX8654) += sx8654.o | ||
82 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | 85 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o |
83 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o | 86 | obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o |
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index ba30578e296e..f0b954d46a25 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c | |||
@@ -157,7 +157,7 @@ static const struct i2c_device_id ar1021_i2c_id[] = { | |||
157 | }; | 157 | }; |
158 | MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); | 158 | MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); |
159 | 159 | ||
160 | static struct of_device_id ar1021_i2c_of_match[] = { | 160 | static const struct of_device_id ar1021_i2c_of_match[] = { |
161 | { .compatible = "microchip,ar1021-i2c", }, | 161 | { .compatible = "microchip,ar1021-i2c", }, |
162 | { } | 162 | { } |
163 | }; | 163 | }; |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 95ee92a91bd2..2875ddf37289 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/of.h> | 26 | #include <linux/of.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <asm/unaligned.h> | ||
28 | 29 | ||
29 | /* Version */ | 30 | /* Version */ |
30 | #define MXT_VER_20 20 | 31 | #define MXT_VER_20 20 |
@@ -79,6 +80,7 @@ | |||
79 | #define MXT_SPT_DIGITIZER_T43 43 | 80 | #define MXT_SPT_DIGITIZER_T43 43 |
80 | #define MXT_SPT_MESSAGECOUNT_T44 44 | 81 | #define MXT_SPT_MESSAGECOUNT_T44 44 |
81 | #define MXT_SPT_CTECONFIG_T46 46 | 82 | #define MXT_SPT_CTECONFIG_T46 46 |
83 | #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 | ||
82 | 84 | ||
83 | /* MXT_GEN_MESSAGE_T5 object */ | 85 | /* MXT_GEN_MESSAGE_T5 object */ |
84 | #define MXT_RPTID_NOMSG 0xff | 86 | #define MXT_RPTID_NOMSG 0xff |
@@ -185,6 +187,36 @@ struct t9_range { | |||
185 | #define MXT_RESET_VALUE 0x01 | 187 | #define MXT_RESET_VALUE 0x01 |
186 | #define MXT_BACKUP_VALUE 0x55 | 188 | #define MXT_BACKUP_VALUE 0x55 |
187 | 189 | ||
190 | /* T100 Multiple Touch Touchscreen */ | ||
191 | #define MXT_T100_CTRL 0 | ||
192 | #define MXT_T100_CFG1 1 | ||
193 | #define MXT_T100_TCHAUX 3 | ||
194 | #define MXT_T100_XRANGE 13 | ||
195 | #define MXT_T100_YRANGE 24 | ||
196 | |||
197 | #define MXT_T100_CFG_SWITCHXY BIT(5) | ||
198 | |||
199 | #define MXT_T100_TCHAUX_VECT BIT(0) | ||
200 | #define MXT_T100_TCHAUX_AMPL BIT(1) | ||
201 | #define MXT_T100_TCHAUX_AREA BIT(2) | ||
202 | |||
203 | #define MXT_T100_DETECT BIT(7) | ||
204 | #define MXT_T100_TYPE_MASK 0x70 | ||
205 | |||
206 | enum t100_type { | ||
207 | MXT_T100_TYPE_FINGER = 1, | ||
208 | MXT_T100_TYPE_PASSIVE_STYLUS = 2, | ||
209 | MXT_T100_TYPE_HOVERING_FINGER = 4, | ||
210 | MXT_T100_TYPE_GLOVE = 5, | ||
211 | MXT_T100_TYPE_LARGE_TOUCH = 6, | ||
212 | }; | ||
213 | |||
214 | #define MXT_DISTANCE_ACTIVE_TOUCH 0 | ||
215 | #define MXT_DISTANCE_HOVERING 1 | ||
216 | |||
217 | #define MXT_TOUCH_MAJOR_DEFAULT 1 | ||
218 | #define MXT_PRESSURE_DEFAULT 1 | ||
219 | |||
188 | /* Delay times */ | 220 | /* Delay times */ |
189 | #define MXT_BACKUP_TIME 50 /* msec */ | 221 | #define MXT_BACKUP_TIME 50 /* msec */ |
190 | #define MXT_RESET_TIME 200 /* msec */ | 222 | #define MXT_RESET_TIME 200 /* msec */ |
@@ -244,6 +276,9 @@ struct mxt_data { | |||
244 | unsigned int max_y; | 276 | unsigned int max_y; |
245 | bool in_bootloader; | 277 | bool in_bootloader; |
246 | u16 mem_size; | 278 | u16 mem_size; |
279 | u8 t100_aux_ampl; | ||
280 | u8 t100_aux_area; | ||
281 | u8 t100_aux_vect; | ||
247 | u8 max_reportid; | 282 | u8 max_reportid; |
248 | u32 config_crc; | 283 | u32 config_crc; |
249 | u32 info_crc; | 284 | u32 info_crc; |
@@ -253,6 +288,7 @@ struct mxt_data { | |||
253 | bool update_input; | 288 | bool update_input; |
254 | u8 last_message_count; | 289 | u8 last_message_count; |
255 | u8 num_touchids; | 290 | u8 num_touchids; |
291 | u8 multitouch; | ||
256 | 292 | ||
257 | /* Cached parameters from object table */ | 293 | /* Cached parameters from object table */ |
258 | u16 T5_address; | 294 | u16 T5_address; |
@@ -264,6 +300,8 @@ struct mxt_data { | |||
264 | u8 T9_reportid_max; | 300 | u8 T9_reportid_max; |
265 | u8 T19_reportid; | 301 | u8 T19_reportid; |
266 | u16 T44_address; | 302 | u16 T44_address; |
303 | u8 T100_reportid_min; | ||
304 | u8 T100_reportid_max; | ||
267 | 305 | ||
268 | /* for fw update in bootloader */ | 306 | /* for fw update in bootloader */ |
269 | struct completion bl_completion; | 307 | struct completion bl_completion; |
@@ -771,6 +809,114 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) | |||
771 | data->update_input = true; | 809 | data->update_input = true; |
772 | } | 810 | } |
773 | 811 | ||
812 | static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) | ||
813 | { | ||
814 | struct device *dev = &data->client->dev; | ||
815 | struct input_dev *input_dev = data->input_dev; | ||
816 | int id; | ||
817 | u8 status; | ||
818 | u8 type = 0; | ||
819 | u16 x; | ||
820 | u16 y; | ||
821 | int distance = 0; | ||
822 | int tool = 0; | ||
823 | u8 major = 0; | ||
824 | u8 pressure = 0; | ||
825 | u8 orientation = 0; | ||
826 | |||
827 | id = message[0] - data->T100_reportid_min - 2; | ||
828 | |||
829 | /* ignore SCRSTATUS events */ | ||
830 | if (id < 0) | ||
831 | return; | ||
832 | |||
833 | status = message[1]; | ||
834 | x = get_unaligned_le16(&message[2]); | ||
835 | y = get_unaligned_le16(&message[4]); | ||
836 | |||
837 | if (status & MXT_T100_DETECT) { | ||
838 | type = (status & MXT_T100_TYPE_MASK) >> 4; | ||
839 | |||
840 | switch (type) { | ||
841 | case MXT_T100_TYPE_HOVERING_FINGER: | ||
842 | tool = MT_TOOL_FINGER; | ||
843 | distance = MXT_DISTANCE_HOVERING; | ||
844 | |||
845 | if (data->t100_aux_vect) | ||
846 | orientation = message[data->t100_aux_vect]; | ||
847 | |||
848 | break; | ||
849 | |||
850 | case MXT_T100_TYPE_FINGER: | ||
851 | case MXT_T100_TYPE_GLOVE: | ||
852 | tool = MT_TOOL_FINGER; | ||
853 | distance = MXT_DISTANCE_ACTIVE_TOUCH; | ||
854 | |||
855 | if (data->t100_aux_area) | ||
856 | major = message[data->t100_aux_area]; | ||
857 | |||
858 | if (data->t100_aux_ampl) | ||
859 | pressure = message[data->t100_aux_ampl]; | ||
860 | |||
861 | if (data->t100_aux_vect) | ||
862 | orientation = message[data->t100_aux_vect]; | ||
863 | |||
864 | break; | ||
865 | |||
866 | case MXT_T100_TYPE_PASSIVE_STYLUS: | ||
867 | tool = MT_TOOL_PEN; | ||
868 | |||
869 | /* | ||
870 | * Passive stylus is reported with size zero so | ||
871 | * hardcode. | ||
872 | */ | ||
873 | major = MXT_TOUCH_MAJOR_DEFAULT; | ||
874 | |||
875 | if (data->t100_aux_ampl) | ||
876 | pressure = message[data->t100_aux_ampl]; | ||
877 | |||
878 | break; | ||
879 | |||
880 | case MXT_T100_TYPE_LARGE_TOUCH: | ||
881 | /* Ignore suppressed touch */ | ||
882 | break; | ||
883 | |||
884 | default: | ||
885 | dev_dbg(dev, "Unexpected T100 type\n"); | ||
886 | return; | ||
887 | } | ||
888 | } | ||
889 | |||
890 | /* | ||
891 | * Values reported should be non-zero if tool is touching the | ||
892 | * device | ||
893 | */ | ||
894 | if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER) | ||
895 | pressure = MXT_PRESSURE_DEFAULT; | ||
896 | |||
897 | input_mt_slot(input_dev, id); | ||
898 | |||
899 | if (status & MXT_T100_DETECT) { | ||
900 | dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n", | ||
901 | id, type, x, y, major, pressure, orientation); | ||
902 | |||
903 | input_mt_report_slot_state(input_dev, tool, 1); | ||
904 | input_report_abs(input_dev, ABS_MT_POSITION_X, x); | ||
905 | input_report_abs(input_dev, ABS_MT_POSITION_Y, y); | ||
906 | input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major); | ||
907 | input_report_abs(input_dev, ABS_MT_PRESSURE, pressure); | ||
908 | input_report_abs(input_dev, ABS_MT_DISTANCE, distance); | ||
909 | input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation); | ||
910 | } else { | ||
911 | dev_dbg(dev, "[%u] release\n", id); | ||
912 | |||
913 | /* close out slot */ | ||
914 | input_mt_report_slot_state(input_dev, 0, 0); | ||
915 | } | ||
916 | |||
917 | data->update_input = true; | ||
918 | } | ||
919 | |||
774 | static int mxt_proc_message(struct mxt_data *data, u8 *message) | 920 | static int mxt_proc_message(struct mxt_data *data, u8 *message) |
775 | { | 921 | { |
776 | u8 report_id = message[0]; | 922 | u8 report_id = message[0]; |
@@ -786,9 +932,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) | |||
786 | * is not yet registered. | 932 | * is not yet registered. |
787 | */ | 933 | */ |
788 | mxt_dump_message(data, message); | 934 | mxt_dump_message(data, message); |
789 | } else if (report_id >= data->T9_reportid_min | 935 | } else if (report_id >= data->T9_reportid_min && |
790 | && report_id <= data->T9_reportid_max) { | 936 | report_id <= data->T9_reportid_max) { |
791 | mxt_proc_t9_message(data, message); | 937 | mxt_proc_t9_message(data, message); |
938 | } else if (report_id >= data->T100_reportid_min && | ||
939 | report_id <= data->T100_reportid_max) { | ||
940 | mxt_proc_t100_message(data, message); | ||
792 | } else if (report_id == data->T19_reportid) { | 941 | } else if (report_id == data->T19_reportid) { |
793 | mxt_input_button(data, message); | 942 | mxt_input_button(data, message); |
794 | data->update_input = true; | 943 | data->update_input = true; |
@@ -1411,6 +1560,8 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
1411 | data->T9_reportid_max = 0; | 1560 | data->T9_reportid_max = 0; |
1412 | data->T19_reportid = 0; | 1561 | data->T19_reportid = 0; |
1413 | data->T44_address = 0; | 1562 | data->T44_address = 0; |
1563 | data->T100_reportid_min = 0; | ||
1564 | data->T100_reportid_max = 0; | ||
1414 | data->max_reportid = 0; | 1565 | data->max_reportid = 0; |
1415 | } | 1566 | } |
1416 | 1567 | ||
@@ -1487,6 +1638,7 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1487 | data->T7_address = object->start_address; | 1638 | data->T7_address = object->start_address; |
1488 | break; | 1639 | break; |
1489 | case MXT_TOUCH_MULTI_T9: | 1640 | case MXT_TOUCH_MULTI_T9: |
1641 | data->multitouch = MXT_TOUCH_MULTI_T9; | ||
1490 | data->T9_reportid_min = min_id; | 1642 | data->T9_reportid_min = min_id; |
1491 | data->T9_reportid_max = max_id; | 1643 | data->T9_reportid_max = max_id; |
1492 | data->num_touchids = object->num_report_ids | 1644 | data->num_touchids = object->num_report_ids |
@@ -1498,6 +1650,13 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
1498 | case MXT_SPT_GPIOPWM_T19: | 1650 | case MXT_SPT_GPIOPWM_T19: |
1499 | data->T19_reportid = min_id; | 1651 | data->T19_reportid = min_id; |
1500 | break; | 1652 | break; |
1653 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: | ||
1654 | data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; | ||
1655 | data->T100_reportid_min = min_id; | ||
1656 | data->T100_reportid_max = max_id; | ||
1657 | /* first two report IDs reserved */ | ||
1658 | data->num_touchids = object->num_report_ids - 2; | ||
1659 | break; | ||
1501 | } | 1660 | } |
1502 | 1661 | ||
1503 | end_address = object->start_address | 1662 | end_address = object->start_address |
@@ -1582,22 +1741,138 @@ static int mxt_read_t9_resolution(struct mxt_data *data) | |||
1582 | return 0; | 1741 | return 0; |
1583 | } | 1742 | } |
1584 | 1743 | ||
1744 | static int mxt_read_t100_config(struct mxt_data *data) | ||
1745 | { | ||
1746 | struct i2c_client *client = data->client; | ||
1747 | int error; | ||
1748 | struct mxt_object *object; | ||
1749 | u16 range_x, range_y; | ||
1750 | u8 cfg, tchaux; | ||
1751 | u8 aux; | ||
1752 | |||
1753 | object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100); | ||
1754 | if (!object) | ||
1755 | return -EINVAL; | ||
1756 | |||
1757 | error = __mxt_read_reg(client, | ||
1758 | object->start_address + MXT_T100_XRANGE, | ||
1759 | sizeof(range_x), &range_x); | ||
1760 | if (error) | ||
1761 | return error; | ||
1762 | |||
1763 | le16_to_cpus(&range_x); | ||
1764 | |||
1765 | error = __mxt_read_reg(client, | ||
1766 | object->start_address + MXT_T100_YRANGE, | ||
1767 | sizeof(range_y), &range_y); | ||
1768 | if (error) | ||
1769 | return error; | ||
1770 | |||
1771 | le16_to_cpus(&range_y); | ||
1772 | |||
1773 | error = __mxt_read_reg(client, | ||
1774 | object->start_address + MXT_T100_CFG1, | ||
1775 | 1, &cfg); | ||
1776 | if (error) | ||
1777 | return error; | ||
1778 | |||
1779 | error = __mxt_read_reg(client, | ||
1780 | object->start_address + MXT_T100_TCHAUX, | ||
1781 | 1, &tchaux); | ||
1782 | if (error) | ||
1783 | return error; | ||
1784 | |||
1785 | /* Handle default values */ | ||
1786 | if (range_x == 0) | ||
1787 | range_x = 1023; | ||
1788 | |||
1789 | if (range_y == 0) | ||
1790 | range_y = 1023; | ||
1791 | |||
1792 | if (cfg & MXT_T100_CFG_SWITCHXY) { | ||
1793 | data->max_x = range_y; | ||
1794 | data->max_y = range_x; | ||
1795 | } else { | ||
1796 | data->max_x = range_x; | ||
1797 | data->max_y = range_y; | ||
1798 | } | ||
1799 | |||
1800 | /* allocate aux bytes */ | ||
1801 | aux = 6; | ||
1802 | |||
1803 | if (tchaux & MXT_T100_TCHAUX_VECT) | ||
1804 | data->t100_aux_vect = aux++; | ||
1805 | |||
1806 | if (tchaux & MXT_T100_TCHAUX_AMPL) | ||
1807 | data->t100_aux_ampl = aux++; | ||
1808 | |||
1809 | if (tchaux & MXT_T100_TCHAUX_AREA) | ||
1810 | data->t100_aux_area = aux++; | ||
1811 | |||
1812 | dev_dbg(&client->dev, | ||
1813 | "T100 aux mappings vect:%u ampl:%u area:%u\n", | ||
1814 | data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area); | ||
1815 | |||
1816 | dev_info(&client->dev, | ||
1817 | "T100 Touchscreen size X%uY%u\n", data->max_x, data->max_y); | ||
1818 | |||
1819 | return 0; | ||
1820 | } | ||
1821 | |||
1585 | static int mxt_input_open(struct input_dev *dev); | 1822 | static int mxt_input_open(struct input_dev *dev); |
1586 | static void mxt_input_close(struct input_dev *dev); | 1823 | static void mxt_input_close(struct input_dev *dev); |
1587 | 1824 | ||
1588 | static int mxt_initialize_t9_input_device(struct mxt_data *data) | 1825 | static void mxt_set_up_as_touchpad(struct input_dev *input_dev, |
1826 | struct mxt_data *data) | ||
1589 | { | 1827 | { |
1590 | struct device *dev = &data->client->dev; | ||
1591 | const struct mxt_platform_data *pdata = data->pdata; | 1828 | const struct mxt_platform_data *pdata = data->pdata; |
1829 | int i; | ||
1830 | |||
1831 | input_dev->name = "Atmel maXTouch Touchpad"; | ||
1832 | |||
1833 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
1834 | |||
1835 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1836 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1837 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1838 | MXT_PIXELS_PER_MM); | ||
1839 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1840 | MXT_PIXELS_PER_MM); | ||
1841 | |||
1842 | for (i = 0; i < pdata->t19_num_keys; i++) | ||
1843 | if (pdata->t19_keymap[i] != KEY_RESERVED) | ||
1844 | input_set_capability(input_dev, EV_KEY, | ||
1845 | pdata->t19_keymap[i]); | ||
1846 | } | ||
1847 | |||
1848 | static int mxt_initialize_input_device(struct mxt_data *data) | ||
1849 | { | ||
1850 | const struct mxt_platform_data *pdata = data->pdata; | ||
1851 | struct device *dev = &data->client->dev; | ||
1592 | struct input_dev *input_dev; | 1852 | struct input_dev *input_dev; |
1593 | int error; | 1853 | int error; |
1594 | unsigned int num_mt_slots; | 1854 | unsigned int num_mt_slots; |
1595 | unsigned int mt_flags = 0; | 1855 | unsigned int mt_flags = 0; |
1596 | int i; | ||
1597 | 1856 | ||
1598 | error = mxt_read_t9_resolution(data); | 1857 | switch (data->multitouch) { |
1599 | if (error) | 1858 | case MXT_TOUCH_MULTI_T9: |
1600 | dev_warn(dev, "Failed to initialize T9 resolution\n"); | 1859 | num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; |
1860 | error = mxt_read_t9_resolution(data); | ||
1861 | if (error) | ||
1862 | dev_warn(dev, "Failed to initialize T9 resolution\n"); | ||
1863 | break; | ||
1864 | |||
1865 | case MXT_TOUCH_MULTITOUCHSCREEN_T100: | ||
1866 | num_mt_slots = data->num_touchids; | ||
1867 | error = mxt_read_t100_config(data); | ||
1868 | if (error) | ||
1869 | dev_warn(dev, "Failed to read T100 config\n"); | ||
1870 | break; | ||
1871 | |||
1872 | default: | ||
1873 | dev_err(dev, "Invalid multitouch object\n"); | ||
1874 | return -EINVAL; | ||
1875 | } | ||
1601 | 1876 | ||
1602 | input_dev = input_allocate_device(); | 1877 | input_dev = input_allocate_device(); |
1603 | if (!input_dev) { | 1878 | if (!input_dev) { |
@@ -1612,54 +1887,76 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data) | |||
1612 | input_dev->open = mxt_input_open; | 1887 | input_dev->open = mxt_input_open; |
1613 | input_dev->close = mxt_input_close; | 1888 | input_dev->close = mxt_input_close; |
1614 | 1889 | ||
1615 | __set_bit(EV_ABS, input_dev->evbit); | 1890 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); |
1616 | __set_bit(EV_KEY, input_dev->evbit); | ||
1617 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
1618 | 1891 | ||
1619 | if (pdata->t19_num_keys) { | 1892 | /* For single touch */ |
1620 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | 1893 | input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0); |
1894 | input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0); | ||
1621 | 1895 | ||
1622 | for (i = 0; i < pdata->t19_num_keys; i++) | 1896 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || |
1623 | if (pdata->t19_keymap[i] != KEY_RESERVED) | 1897 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && |
1624 | input_set_capability(input_dev, EV_KEY, | 1898 | data->t100_aux_ampl)) { |
1625 | pdata->t19_keymap[i]); | 1899 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); |
1900 | } | ||
1626 | 1901 | ||
1902 | /* If device has buttons we assume it is a touchpad */ | ||
1903 | if (pdata->t19_num_keys) { | ||
1904 | mxt_set_up_as_touchpad(input_dev, data); | ||
1627 | mt_flags |= INPUT_MT_POINTER; | 1905 | mt_flags |= INPUT_MT_POINTER; |
1628 | |||
1629 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1630 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1631 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1632 | MXT_PIXELS_PER_MM); | ||
1633 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1634 | MXT_PIXELS_PER_MM); | ||
1635 | |||
1636 | input_dev->name = "Atmel maXTouch Touchpad"; | ||
1637 | } | 1906 | } |
1638 | 1907 | ||
1639 | /* For single touch */ | ||
1640 | input_set_abs_params(input_dev, ABS_X, | ||
1641 | 0, data->max_x, 0, 0); | ||
1642 | input_set_abs_params(input_dev, ABS_Y, | ||
1643 | 0, data->max_y, 0, 0); | ||
1644 | input_set_abs_params(input_dev, ABS_PRESSURE, | ||
1645 | 0, 255, 0, 0); | ||
1646 | |||
1647 | /* For multi touch */ | 1908 | /* For multi touch */ |
1648 | num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; | ||
1649 | error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); | 1909 | error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); |
1650 | if (error) { | 1910 | if (error) { |
1651 | dev_err(dev, "Error %d initialising slots\n", error); | 1911 | dev_err(dev, "Error %d initialising slots\n", error); |
1652 | goto err_free_mem; | 1912 | goto err_free_mem; |
1653 | } | 1913 | } |
1654 | 1914 | ||
1655 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | 1915 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { |
1656 | 0, MXT_MAX_AREA, 0, 0); | 1916 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, |
1917 | 0, MT_TOOL_MAX, 0, 0); | ||
1918 | input_set_abs_params(input_dev, ABS_MT_DISTANCE, | ||
1919 | MXT_DISTANCE_ACTIVE_TOUCH, | ||
1920 | MXT_DISTANCE_HOVERING, | ||
1921 | 0, 0); | ||
1922 | } | ||
1923 | |||
1657 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1924 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
1658 | 0, data->max_x, 0, 0); | 1925 | 0, data->max_x, 0, 0); |
1659 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | 1926 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, |
1660 | 0, data->max_y, 0, 0); | 1927 | 0, data->max_y, 0, 0); |
1661 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | 1928 | |
1662 | 0, 255, 0, 0); | 1929 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || |
1930 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1931 | data->t100_aux_area)) { | ||
1932 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
1933 | 0, MXT_MAX_AREA, 0, 0); | ||
1934 | } | ||
1935 | |||
1936 | if (data->multitouch == MXT_TOUCH_MULTI_T9 || | ||
1937 | (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1938 | data->t100_aux_ampl)) { | ||
1939 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1940 | 0, 255, 0, 0); | ||
1941 | } | ||
1942 | |||
1943 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1944 | data->t100_aux_vect) { | ||
1945 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, | ||
1946 | 0, 255, 0, 0); | ||
1947 | } | ||
1948 | |||
1949 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1950 | data->t100_aux_ampl) { | ||
1951 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, | ||
1952 | 0, 255, 0, 0); | ||
1953 | } | ||
1954 | |||
1955 | if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && | ||
1956 | data->t100_aux_vect) { | ||
1957 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, | ||
1958 | 0, 255, 0, 0); | ||
1959 | } | ||
1663 | 1960 | ||
1664 | input_set_drvdata(input_dev, data); | 1961 | input_set_drvdata(input_dev, data); |
1665 | 1962 | ||
@@ -1765,9 +2062,13 @@ static int mxt_configure_objects(struct mxt_data *data, | |||
1765 | dev_warn(dev, "Error %d updating config\n", error); | 2062 | dev_warn(dev, "Error %d updating config\n", error); |
1766 | } | 2063 | } |
1767 | 2064 | ||
1768 | error = mxt_initialize_t9_input_device(data); | 2065 | if (data->multitouch) { |
1769 | if (error) | 2066 | error = mxt_initialize_input_device(data); |
1770 | return error; | 2067 | if (error) |
2068 | return error; | ||
2069 | } else { | ||
2070 | dev_warn(dev, "No touch object detected\n"); | ||
2071 | } | ||
1771 | 2072 | ||
1772 | dev_info(dev, | 2073 | dev_info(dev, |
1773 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", | 2074 | "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", |
@@ -2044,15 +2345,13 @@ static const struct attribute_group mxt_attr_group = { | |||
2044 | static void mxt_start(struct mxt_data *data) | 2345 | static void mxt_start(struct mxt_data *data) |
2045 | { | 2346 | { |
2046 | /* Touch enable */ | 2347 | /* Touch enable */ |
2047 | mxt_write_object(data, | 2348 | mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0x83); |
2048 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); | ||
2049 | } | 2349 | } |
2050 | 2350 | ||
2051 | static void mxt_stop(struct mxt_data *data) | 2351 | static void mxt_stop(struct mxt_data *data) |
2052 | { | 2352 | { |
2053 | /* Touch disable */ | 2353 | /* Touch disable */ |
2054 | mxt_write_object(data, | 2354 | mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0); |
2055 | MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); | ||
2056 | } | 2355 | } |
2057 | 2356 | ||
2058 | static int mxt_input_open(struct input_dev *dev) | 2357 | static int mxt_input_open(struct input_dev *dev) |
diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c new file mode 100644 index 000000000000..ae460a5c93d5 --- /dev/null +++ b/drivers/input/touchscreen/bcm_iproc_tsc.c | |||
@@ -0,0 +1,522 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/keyboard.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/serio.h> | ||
26 | |||
27 | #define IPROC_TS_NAME "iproc-ts" | ||
28 | |||
29 | #define PEN_DOWN_STATUS 1 | ||
30 | #define PEN_UP_STATUS 0 | ||
31 | |||
32 | #define X_MIN 0 | ||
33 | #define Y_MIN 0 | ||
34 | #define X_MAX 0xFFF | ||
35 | #define Y_MAX 0xFFF | ||
36 | |||
37 | /* Value given by controller for invalid coordinate. */ | ||
38 | #define INVALID_COORD 0xFFFFFFFF | ||
39 | |||
40 | /* Register offsets */ | ||
41 | #define REGCTL1 0x00 | ||
42 | #define REGCTL2 0x04 | ||
43 | #define INTERRUPT_THRES 0x08 | ||
44 | #define INTERRUPT_MASK 0x0c | ||
45 | |||
46 | #define INTERRUPT_STATUS 0x10 | ||
47 | #define CONTROLLER_STATUS 0x14 | ||
48 | #define FIFO_DATA 0x18 | ||
49 | #define FIFO_DATA_X_Y_MASK 0xFFFF | ||
50 | #define ANALOG_CONTROL 0x1c | ||
51 | |||
52 | #define AUX_DATA 0x20 | ||
53 | #define DEBOUNCE_CNTR_STAT 0x24 | ||
54 | #define SCAN_CNTR_STAT 0x28 | ||
55 | #define REM_CNTR_STAT 0x2c | ||
56 | |||
57 | #define SETTLING_TIMER_STAT 0x30 | ||
58 | #define SPARE_REG 0x34 | ||
59 | #define SOFT_BYPASS_CONTROL 0x38 | ||
60 | #define SOFT_BYPASS_DATA 0x3c | ||
61 | |||
62 | |||
63 | /* Bit values for INTERRUPT_MASK and INTERRUPT_STATUS regs */ | ||
64 | #define TS_PEN_INTR_MASK BIT(0) | ||
65 | #define TS_FIFO_INTR_MASK BIT(2) | ||
66 | |||
67 | /* Bit values for CONTROLLER_STATUS reg1 */ | ||
68 | #define TS_PEN_DOWN BIT(0) | ||
69 | |||
70 | /* Shift values for control reg1 */ | ||
71 | #define SCANNING_PERIOD_SHIFT 24 | ||
72 | #define DEBOUNCE_TIMEOUT_SHIFT 16 | ||
73 | #define SETTLING_TIMEOUT_SHIFT 8 | ||
74 | #define TOUCH_TIMEOUT_SHIFT 0 | ||
75 | |||
76 | /* Shift values for coordinates from fifo */ | ||
77 | #define X_COORD_SHIFT 0 | ||
78 | #define Y_COORD_SHIFT 16 | ||
79 | |||
80 | /* Bit values for REGCTL2 */ | ||
81 | #define TS_CONTROLLER_EN_BIT BIT(16) | ||
82 | #define TS_CONTROLLER_AVGDATA_SHIFT 8 | ||
83 | #define TS_CONTROLLER_AVGDATA_MASK (0x7 << TS_CONTROLLER_AVGDATA_SHIFT) | ||
84 | #define TS_CONTROLLER_PWR_LDO BIT(5) | ||
85 | #define TS_CONTROLLER_PWR_ADC BIT(4) | ||
86 | #define TS_CONTROLLER_PWR_BGP BIT(3) | ||
87 | #define TS_CONTROLLER_PWR_TS BIT(2) | ||
88 | #define TS_WIRE_MODE_BIT BIT(1) | ||
89 | |||
90 | #define dbg_reg(dev, priv, reg) \ | ||
91 | dev_dbg(dev, "%20s= 0x%08x\n", #reg, readl((priv)->regs + reg)) | ||
92 | |||
93 | struct tsc_param { | ||
94 | /* Each step is 1024 us. Valid 1-256 */ | ||
95 | u32 scanning_period; | ||
96 | |||
97 | /* Each step is 512 us. Valid 0-255 */ | ||
98 | u32 debounce_timeout; | ||
99 | |||
100 | /* | ||
101 | * The settling duration (in ms) is the amount of time the tsc | ||
102 | * waits to allow the voltage to settle after turning on the | ||
103 | * drivers in detection mode. Valid values: 0-11 | ||
104 | * 0 = 0.008 ms | ||
105 | * 1 = 0.01 ms | ||
106 | * 2 = 0.02 ms | ||
107 | * 3 = 0.04 ms | ||
108 | * 4 = 0.08 ms | ||
109 | * 5 = 0.16 ms | ||
110 | * 6 = 0.32 ms | ||
111 | * 7 = 0.64 ms | ||
112 | * 8 = 1.28 ms | ||
113 | * 9 = 2.56 ms | ||
114 | * 10 = 5.12 ms | ||
115 | * 11 = 10.24 ms | ||
116 | */ | ||
117 | u32 settling_timeout; | ||
118 | |||
119 | /* touch timeout in sample counts */ | ||
120 | u32 touch_timeout; | ||
121 | |||
122 | /* | ||
123 | * Number of data samples which are averaged before a final data point | ||
124 | * is placed into the FIFO | ||
125 | */ | ||
126 | u32 average_data; | ||
127 | |||
128 | /* FIFO threshold */ | ||
129 | u32 fifo_threshold; | ||
130 | |||
131 | /* Optional standard touchscreen properties. */ | ||
132 | u32 max_x; | ||
133 | u32 max_y; | ||
134 | u32 fuzz_x; | ||
135 | u32 fuzz_y; | ||
136 | bool invert_x; | ||
137 | bool invert_y; | ||
138 | }; | ||
139 | |||
140 | struct iproc_ts_priv { | ||
141 | struct platform_device *pdev; | ||
142 | struct input_dev *idev; | ||
143 | |||
144 | void __iomem *regs; | ||
145 | struct clk *tsc_clk; | ||
146 | |||
147 | int pen_status; | ||
148 | struct tsc_param cfg_params; | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * Set default values the same as hardware reset values | ||
153 | * except for fifo_threshold with is set to 1. | ||
154 | */ | ||
155 | static const struct tsc_param iproc_default_config = { | ||
156 | .scanning_period = 0x5, /* 1 to 256 */ | ||
157 | .debounce_timeout = 0x28, /* 0 to 255 */ | ||
158 | .settling_timeout = 0x7, /* 0 to 11 */ | ||
159 | .touch_timeout = 0xa, /* 0 to 255 */ | ||
160 | .average_data = 5, /* entry 5 = 32 pts */ | ||
161 | .fifo_threshold = 1, /* 0 to 31 */ | ||
162 | .max_x = X_MAX, | ||
163 | .max_y = Y_MAX, | ||
164 | }; | ||
165 | |||
166 | static void ts_reg_dump(struct iproc_ts_priv *priv) | ||
167 | { | ||
168 | struct device *dev = &priv->pdev->dev; | ||
169 | |||
170 | dbg_reg(dev, priv, REGCTL1); | ||
171 | dbg_reg(dev, priv, REGCTL2); | ||
172 | dbg_reg(dev, priv, INTERRUPT_THRES); | ||
173 | dbg_reg(dev, priv, INTERRUPT_MASK); | ||
174 | dbg_reg(dev, priv, INTERRUPT_STATUS); | ||
175 | dbg_reg(dev, priv, CONTROLLER_STATUS); | ||
176 | dbg_reg(dev, priv, FIFO_DATA); | ||
177 | dbg_reg(dev, priv, ANALOG_CONTROL); | ||
178 | dbg_reg(dev, priv, AUX_DATA); | ||
179 | dbg_reg(dev, priv, DEBOUNCE_CNTR_STAT); | ||
180 | dbg_reg(dev, priv, SCAN_CNTR_STAT); | ||
181 | dbg_reg(dev, priv, REM_CNTR_STAT); | ||
182 | dbg_reg(dev, priv, SETTLING_TIMER_STAT); | ||
183 | dbg_reg(dev, priv, SPARE_REG); | ||
184 | dbg_reg(dev, priv, SOFT_BYPASS_CONTROL); | ||
185 | dbg_reg(dev, priv, SOFT_BYPASS_DATA); | ||
186 | } | ||
187 | |||
188 | static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) | ||
189 | { | ||
190 | struct platform_device *pdev = data; | ||
191 | struct iproc_ts_priv *priv = platform_get_drvdata(pdev); | ||
192 | u32 intr_status; | ||
193 | u32 raw_coordinate; | ||
194 | u16 x; | ||
195 | u16 y; | ||
196 | int i; | ||
197 | bool needs_sync = false; | ||
198 | |||
199 | intr_status = readl(priv->regs + INTERRUPT_STATUS); | ||
200 | intr_status &= TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; | ||
201 | if (intr_status == 0) | ||
202 | return IRQ_NONE; | ||
203 | |||
204 | /* Clear all interrupt status bits, write-1-clear */ | ||
205 | writel(intr_status, priv->regs + INTERRUPT_STATUS); | ||
206 | |||
207 | /* Pen up/down */ | ||
208 | if (intr_status & TS_PEN_INTR_MASK) { | ||
209 | if (readl(priv->regs + CONTROLLER_STATUS) & TS_PEN_DOWN) | ||
210 | priv->pen_status = PEN_DOWN_STATUS; | ||
211 | else | ||
212 | priv->pen_status = PEN_UP_STATUS; | ||
213 | |||
214 | input_report_key(priv->idev, BTN_TOUCH, priv->pen_status); | ||
215 | needs_sync = true; | ||
216 | |||
217 | dev_dbg(&priv->pdev->dev, | ||
218 | "pen up-down (%d)\n", priv->pen_status); | ||
219 | } | ||
220 | |||
221 | /* coordinates in FIFO exceed the theshold */ | ||
222 | if (intr_status & TS_FIFO_INTR_MASK) { | ||
223 | for (i = 0; i < priv->cfg_params.fifo_threshold; i++) { | ||
224 | raw_coordinate = readl(priv->regs + FIFO_DATA); | ||
225 | if (raw_coordinate == INVALID_COORD) | ||
226 | continue; | ||
227 | |||
228 | /* | ||
229 | * The x and y coordinate are 16 bits each | ||
230 | * with the x in the lower 16 bits and y in the | ||
231 | * upper 16 bits. | ||
232 | */ | ||
233 | x = (raw_coordinate >> X_COORD_SHIFT) & | ||
234 | FIFO_DATA_X_Y_MASK; | ||
235 | y = (raw_coordinate >> Y_COORD_SHIFT) & | ||
236 | FIFO_DATA_X_Y_MASK; | ||
237 | |||
238 | /* We only want to retain the 12 msb of the 16 */ | ||
239 | x = (x >> 4) & 0x0FFF; | ||
240 | y = (y >> 4) & 0x0FFF; | ||
241 | |||
242 | /* adjust x y according to lcd tsc mount angle */ | ||
243 | if (priv->cfg_params.invert_x) | ||
244 | x = priv->cfg_params.max_x - x; | ||
245 | |||
246 | if (priv->cfg_params.invert_y) | ||
247 | y = priv->cfg_params.max_y - y; | ||
248 | |||
249 | input_report_abs(priv->idev, ABS_X, x); | ||
250 | input_report_abs(priv->idev, ABS_Y, y); | ||
251 | needs_sync = true; | ||
252 | |||
253 | dev_dbg(&priv->pdev->dev, "xy (0x%x 0x%x)\n", x, y); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | if (needs_sync) | ||
258 | input_sync(priv->idev); | ||
259 | |||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | static int iproc_ts_start(struct input_dev *idev) | ||
264 | { | ||
265 | struct iproc_ts_priv *priv = input_get_drvdata(idev); | ||
266 | u32 val; | ||
267 | int error; | ||
268 | |||
269 | /* Enable clock */ | ||
270 | error = clk_prepare_enable(priv->tsc_clk); | ||
271 | if (error) { | ||
272 | dev_err(&priv->pdev->dev, "%s clk_prepare_enable failed %d\n", | ||
273 | __func__, error); | ||
274 | return error; | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Interrupt is generated when: | ||
279 | * FIFO reaches the int_th value, and pen event(up/down) | ||
280 | */ | ||
281 | val = TS_PEN_INTR_MASK | TS_FIFO_INTR_MASK; | ||
282 | writel(val, priv->regs + INTERRUPT_MASK); | ||
283 | |||
284 | writel(priv->cfg_params.fifo_threshold, priv->regs + INTERRUPT_THRES); | ||
285 | |||
286 | /* Initialize control reg1 */ | ||
287 | val = 0; | ||
288 | val |= priv->cfg_params.scanning_period << SCANNING_PERIOD_SHIFT; | ||
289 | val |= priv->cfg_params.debounce_timeout << DEBOUNCE_TIMEOUT_SHIFT; | ||
290 | val |= priv->cfg_params.settling_timeout << SETTLING_TIMEOUT_SHIFT; | ||
291 | val |= priv->cfg_params.touch_timeout << TOUCH_TIMEOUT_SHIFT; | ||
292 | writel(val, priv->regs + REGCTL1); | ||
293 | |||
294 | /* Try to clear all interrupt status */ | ||
295 | val = readl(priv->regs + INTERRUPT_STATUS); | ||
296 | val |= TS_FIFO_INTR_MASK | TS_PEN_INTR_MASK; | ||
297 | writel(val, priv->regs + INTERRUPT_STATUS); | ||
298 | |||
299 | /* Initialize control reg2 */ | ||
300 | val = readl(priv->regs + REGCTL2); | ||
301 | val |= TS_CONTROLLER_EN_BIT | TS_WIRE_MODE_BIT; | ||
302 | |||
303 | val &= ~TS_CONTROLLER_AVGDATA_MASK; | ||
304 | val |= priv->cfg_params.average_data << TS_CONTROLLER_AVGDATA_SHIFT; | ||
305 | |||
306 | val &= ~(TS_CONTROLLER_PWR_LDO | /* PWR up LDO */ | ||
307 | TS_CONTROLLER_PWR_ADC | /* PWR up ADC */ | ||
308 | TS_CONTROLLER_PWR_BGP | /* PWR up BGP */ | ||
309 | TS_CONTROLLER_PWR_TS); /* PWR up TS */ | ||
310 | |||
311 | writel(val, priv->regs + REGCTL2); | ||
312 | |||
313 | ts_reg_dump(priv); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static void iproc_ts_stop(struct input_dev *dev) | ||
319 | { | ||
320 | u32 val; | ||
321 | struct iproc_ts_priv *priv = input_get_drvdata(dev); | ||
322 | |||
323 | writel(0, priv->regs + INTERRUPT_MASK); /* Disable all interrupts */ | ||
324 | |||
325 | /* Only power down touch screen controller */ | ||
326 | val = readl(priv->regs + REGCTL2); | ||
327 | val |= TS_CONTROLLER_PWR_TS; | ||
328 | writel(val, priv->regs + REGCTL2); | ||
329 | |||
330 | clk_disable(priv->tsc_clk); | ||
331 | } | ||
332 | |||
333 | static int iproc_get_tsc_config(struct device *dev, struct iproc_ts_priv *priv) | ||
334 | { | ||
335 | struct device_node *np = dev->of_node; | ||
336 | u32 val; | ||
337 | |||
338 | priv->cfg_params = iproc_default_config; | ||
339 | |||
340 | if (!np) | ||
341 | return 0; | ||
342 | |||
343 | if (of_property_read_u32(np, "scanning_period", &val) >= 0) { | ||
344 | if (val < 1 || val > 256) { | ||
345 | dev_err(dev, "scanning_period (%u) must be [1-256]\n", | ||
346 | val); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | priv->cfg_params.scanning_period = val; | ||
350 | } | ||
351 | |||
352 | if (of_property_read_u32(np, "debounce_timeout", &val) >= 0) { | ||
353 | if (val > 255) { | ||
354 | dev_err(dev, "debounce_timeout (%u) must be [0-255]\n", | ||
355 | val); | ||
356 | return -EINVAL; | ||
357 | } | ||
358 | priv->cfg_params.debounce_timeout = val; | ||
359 | } | ||
360 | |||
361 | if (of_property_read_u32(np, "settling_timeout", &val) >= 0) { | ||
362 | if (val > 11) { | ||
363 | dev_err(dev, "settling_timeout (%u) must be [0-11]\n", | ||
364 | val); | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | priv->cfg_params.settling_timeout = val; | ||
368 | } | ||
369 | |||
370 | if (of_property_read_u32(np, "touch_timeout", &val) >= 0) { | ||
371 | if (val > 255) { | ||
372 | dev_err(dev, "touch_timeout (%u) must be [0-255]\n", | ||
373 | val); | ||
374 | return -EINVAL; | ||
375 | } | ||
376 | priv->cfg_params.touch_timeout = val; | ||
377 | } | ||
378 | |||
379 | if (of_property_read_u32(np, "average_data", &val) >= 0) { | ||
380 | if (val > 8) { | ||
381 | dev_err(dev, "average_data (%u) must be [0-8]\n", val); | ||
382 | return -EINVAL; | ||
383 | } | ||
384 | priv->cfg_params.average_data = val; | ||
385 | } | ||
386 | |||
387 | if (of_property_read_u32(np, "fifo_threshold", &val) >= 0) { | ||
388 | if (val > 31) { | ||
389 | dev_err(dev, "fifo_threshold (%u)) must be [0-31]\n", | ||
390 | val); | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | priv->cfg_params.fifo_threshold = val; | ||
394 | } | ||
395 | |||
396 | /* Parse optional properties. */ | ||
397 | of_property_read_u32(np, "touchscreen-size-x", &priv->cfg_params.max_x); | ||
398 | of_property_read_u32(np, "touchscreen-size-y", &priv->cfg_params.max_y); | ||
399 | |||
400 | of_property_read_u32(np, "touchscreen-fuzz-x", | ||
401 | &priv->cfg_params.fuzz_x); | ||
402 | of_property_read_u32(np, "touchscreen-fuzz-y", | ||
403 | &priv->cfg_params.fuzz_y); | ||
404 | |||
405 | priv->cfg_params.invert_x = | ||
406 | of_property_read_bool(np, "touchscreen-inverted-x"); | ||
407 | priv->cfg_params.invert_y = | ||
408 | of_property_read_bool(np, "touchscreen-inverted-y"); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int iproc_ts_probe(struct platform_device *pdev) | ||
414 | { | ||
415 | struct iproc_ts_priv *priv; | ||
416 | struct input_dev *idev; | ||
417 | struct resource *res; | ||
418 | int irq; | ||
419 | int error; | ||
420 | |||
421 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
422 | if (!priv) | ||
423 | return -ENOMEM; | ||
424 | |||
425 | /* touchscreen controller memory mapped regs */ | ||
426 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
427 | priv->regs = devm_ioremap_resource(&pdev->dev, res); | ||
428 | if (IS_ERR(priv->regs)) { | ||
429 | error = PTR_ERR(priv->regs); | ||
430 | dev_err(&pdev->dev, "unable to map I/O memory: %d\n", error); | ||
431 | return error; | ||
432 | } | ||
433 | |||
434 | priv->tsc_clk = devm_clk_get(&pdev->dev, "tsc_clk"); | ||
435 | if (IS_ERR(priv->tsc_clk)) { | ||
436 | error = PTR_ERR(priv->tsc_clk); | ||
437 | dev_err(&pdev->dev, | ||
438 | "failed getting clock tsc_clk: %d\n", error); | ||
439 | return error; | ||
440 | } | ||
441 | |||
442 | priv->pdev = pdev; | ||
443 | error = iproc_get_tsc_config(&pdev->dev, priv); | ||
444 | if (error) { | ||
445 | dev_err(&pdev->dev, "get_tsc_config failed: %d\n", error); | ||
446 | return error; | ||
447 | } | ||
448 | |||
449 | idev = devm_input_allocate_device(&pdev->dev); | ||
450 | if (!idev) { | ||
451 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
452 | return -ENOMEM; | ||
453 | } | ||
454 | |||
455 | priv->idev = idev; | ||
456 | priv->pen_status = PEN_UP_STATUS; | ||
457 | |||
458 | /* Set input device info */ | ||
459 | idev->name = IPROC_TS_NAME; | ||
460 | idev->dev.parent = &pdev->dev; | ||
461 | |||
462 | idev->id.bustype = BUS_HOST; | ||
463 | idev->id.vendor = SERIO_UNKNOWN; | ||
464 | idev->id.product = 0; | ||
465 | idev->id.version = 0; | ||
466 | |||
467 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
468 | __set_bit(BTN_TOUCH, idev->keybit); | ||
469 | |||
470 | input_set_abs_params(idev, ABS_X, X_MIN, priv->cfg_params.max_x, | ||
471 | priv->cfg_params.fuzz_x, 0); | ||
472 | input_set_abs_params(idev, ABS_Y, Y_MIN, priv->cfg_params.max_y, | ||
473 | priv->cfg_params.fuzz_y, 0); | ||
474 | |||
475 | idev->open = iproc_ts_start; | ||
476 | idev->close = iproc_ts_stop; | ||
477 | |||
478 | input_set_drvdata(idev, priv); | ||
479 | platform_set_drvdata(pdev, priv); | ||
480 | |||
481 | /* get interrupt */ | ||
482 | irq = platform_get_irq(pdev, 0); | ||
483 | if (irq < 0) { | ||
484 | dev_err(&pdev->dev, "platform_get_irq failed: %d\n", irq); | ||
485 | return irq; | ||
486 | } | ||
487 | |||
488 | error = devm_request_irq(&pdev->dev, irq, | ||
489 | iproc_touchscreen_interrupt, | ||
490 | IRQF_SHARED, IPROC_TS_NAME, pdev); | ||
491 | if (error) | ||
492 | return error; | ||
493 | |||
494 | error = input_register_device(priv->idev); | ||
495 | if (error) { | ||
496 | dev_err(&pdev->dev, | ||
497 | "failed to register input device: %d\n", error); | ||
498 | return error; | ||
499 | } | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static const struct of_device_id iproc_ts_of_match[] = { | ||
505 | {.compatible = "brcm,iproc-touchscreen", }, | ||
506 | { }, | ||
507 | }; | ||
508 | MODULE_DEVICE_TABLE(of, iproc_ts_of_match); | ||
509 | |||
510 | static struct platform_driver iproc_ts_driver = { | ||
511 | .probe = iproc_ts_probe, | ||
512 | .driver = { | ||
513 | .name = IPROC_TS_NAME, | ||
514 | .of_match_table = of_match_ptr(iproc_ts_of_match), | ||
515 | }, | ||
516 | }; | ||
517 | |||
518 | module_platform_driver(iproc_ts_driver); | ||
519 | |||
520 | MODULE_DESCRIPTION("IPROC Touchscreen driver"); | ||
521 | MODULE_AUTHOR("Broadcom"); | ||
522 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c new file mode 100644 index 000000000000..32e9db0e04bf --- /dev/null +++ b/drivers/input/touchscreen/chipone_icn8318.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * Driver for ChipOne icn8318 i2c touchscreen controller | ||
3 | * | ||
4 | * Copyright (c) 2015 Red Hat Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * Red Hat authors: | ||
12 | * Hans de Goede <hdegoede@redhat.com> | ||
13 | */ | ||
14 | |||
15 | #include <linux/gpio/consumer.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/input/mt.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of.h> | ||
22 | |||
23 | #define ICN8318_REG_POWER 4 | ||
24 | #define ICN8318_REG_TOUCHDATA 16 | ||
25 | |||
26 | #define ICN8318_POWER_ACTIVE 0 | ||
27 | #define ICN8318_POWER_MONITOR 1 | ||
28 | #define ICN8318_POWER_HIBERNATE 2 | ||
29 | |||
30 | #define ICN8318_MAX_TOUCHES 5 | ||
31 | |||
32 | struct icn8318_touch { | ||
33 | __u8 slot; | ||
34 | __be16 x; | ||
35 | __be16 y; | ||
36 | __u8 pressure; /* Seems more like finger width then pressure really */ | ||
37 | __u8 event; | ||
38 | /* The difference between 2 and 3 is unclear */ | ||
39 | #define ICN8318_EVENT_NO_DATA 1 /* No finger seen yet since wakeup */ | ||
40 | #define ICN8318_EVENT_UPDATE1 2 /* New or updated coordinates */ | ||
41 | #define ICN8318_EVENT_UPDATE2 3 /* New or updated coordinates */ | ||
42 | #define ICN8318_EVENT_END 4 /* Finger lifted */ | ||
43 | } __packed; | ||
44 | |||
45 | struct icn8318_touch_data { | ||
46 | __u8 softbutton; | ||
47 | __u8 touch_count; | ||
48 | struct icn8318_touch touches[ICN8318_MAX_TOUCHES]; | ||
49 | } __packed; | ||
50 | |||
51 | struct icn8318_data { | ||
52 | struct i2c_client *client; | ||
53 | struct input_dev *input; | ||
54 | struct gpio_desc *wake_gpio; | ||
55 | u32 max_x; | ||
56 | u32 max_y; | ||
57 | bool invert_x; | ||
58 | bool invert_y; | ||
59 | bool swap_x_y; | ||
60 | }; | ||
61 | |||
62 | static int icn8318_read_touch_data(struct i2c_client *client, | ||
63 | struct icn8318_touch_data *touch_data) | ||
64 | { | ||
65 | u8 reg = ICN8318_REG_TOUCHDATA; | ||
66 | struct i2c_msg msg[2] = { | ||
67 | { | ||
68 | .addr = client->addr, | ||
69 | .len = 1, | ||
70 | .buf = ® | ||
71 | }, | ||
72 | { | ||
73 | .addr = client->addr, | ||
74 | .flags = I2C_M_RD, | ||
75 | .len = sizeof(struct icn8318_touch_data), | ||
76 | .buf = (u8 *)touch_data | ||
77 | } | ||
78 | }; | ||
79 | |||
80 | return i2c_transfer(client->adapter, msg, 2); | ||
81 | } | ||
82 | |||
83 | static inline bool icn8318_touch_active(u8 event) | ||
84 | { | ||
85 | return (event == ICN8318_EVENT_UPDATE1) || | ||
86 | (event == ICN8318_EVENT_UPDATE2); | ||
87 | } | ||
88 | |||
89 | static irqreturn_t icn8318_irq(int irq, void *dev_id) | ||
90 | { | ||
91 | struct icn8318_data *data = dev_id; | ||
92 | struct device *dev = &data->client->dev; | ||
93 | struct icn8318_touch_data touch_data; | ||
94 | int i, ret, x, y; | ||
95 | |||
96 | ret = icn8318_read_touch_data(data->client, &touch_data); | ||
97 | if (ret < 0) { | ||
98 | dev_err(dev, "Error reading touch data: %d\n", ret); | ||
99 | return IRQ_HANDLED; | ||
100 | } | ||
101 | |||
102 | if (touch_data.softbutton) { | ||
103 | /* | ||
104 | * Other data is invalid when a softbutton is pressed. | ||
105 | * This needs some extra devicetree bindings to map the icn8318 | ||
106 | * softbutton codes to evdev codes. Currently no known devices | ||
107 | * use this. | ||
108 | */ | ||
109 | return IRQ_HANDLED; | ||
110 | } | ||
111 | |||
112 | if (touch_data.touch_count > ICN8318_MAX_TOUCHES) { | ||
113 | dev_warn(dev, "Too much touches %d > %d\n", | ||
114 | touch_data.touch_count, ICN8318_MAX_TOUCHES); | ||
115 | touch_data.touch_count = ICN8318_MAX_TOUCHES; | ||
116 | } | ||
117 | |||
118 | for (i = 0; i < touch_data.touch_count; i++) { | ||
119 | struct icn8318_touch *touch = &touch_data.touches[i]; | ||
120 | bool act = icn8318_touch_active(touch->event); | ||
121 | |||
122 | input_mt_slot(data->input, touch->slot); | ||
123 | input_mt_report_slot_state(data->input, MT_TOOL_FINGER, act); | ||
124 | if (!act) | ||
125 | continue; | ||
126 | |||
127 | x = be16_to_cpu(touch->x); | ||
128 | y = be16_to_cpu(touch->y); | ||
129 | |||
130 | if (data->invert_x) | ||
131 | x = data->max_x - x; | ||
132 | |||
133 | if (data->invert_y) | ||
134 | y = data->max_y - y; | ||
135 | |||
136 | if (!data->swap_x_y) { | ||
137 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, x); | ||
138 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, y); | ||
139 | } else { | ||
140 | input_event(data->input, EV_ABS, ABS_MT_POSITION_X, y); | ||
141 | input_event(data->input, EV_ABS, ABS_MT_POSITION_Y, x); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | input_mt_sync_frame(data->input); | ||
146 | input_sync(data->input); | ||
147 | |||
148 | return IRQ_HANDLED; | ||
149 | } | ||
150 | |||
151 | static int icn8318_start(struct input_dev *dev) | ||
152 | { | ||
153 | struct icn8318_data *data = input_get_drvdata(dev); | ||
154 | |||
155 | enable_irq(data->client->irq); | ||
156 | gpiod_set_value_cansleep(data->wake_gpio, 1); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static void icn8318_stop(struct input_dev *dev) | ||
162 | { | ||
163 | struct icn8318_data *data = input_get_drvdata(dev); | ||
164 | |||
165 | disable_irq(data->client->irq); | ||
166 | i2c_smbus_write_byte_data(data->client, ICN8318_REG_POWER, | ||
167 | ICN8318_POWER_HIBERNATE); | ||
168 | gpiod_set_value_cansleep(data->wake_gpio, 0); | ||
169 | } | ||
170 | |||
171 | #ifdef CONFIG_PM_SLEEP | ||
172 | static int icn8318_suspend(struct device *dev) | ||
173 | { | ||
174 | struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); | ||
175 | |||
176 | mutex_lock(&data->input->mutex); | ||
177 | if (data->input->users) | ||
178 | icn8318_stop(data->input); | ||
179 | mutex_unlock(&data->input->mutex); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int icn8318_resume(struct device *dev) | ||
185 | { | ||
186 | struct icn8318_data *data = i2c_get_clientdata(to_i2c_client(dev)); | ||
187 | |||
188 | mutex_lock(&data->input->mutex); | ||
189 | if (data->input->users) | ||
190 | icn8318_start(data->input); | ||
191 | mutex_unlock(&data->input->mutex); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | #endif | ||
196 | |||
197 | static SIMPLE_DEV_PM_OPS(icn8318_pm_ops, icn8318_suspend, icn8318_resume); | ||
198 | |||
199 | static int icn8318_probe(struct i2c_client *client, | ||
200 | const struct i2c_device_id *id) | ||
201 | { | ||
202 | struct device *dev = &client->dev; | ||
203 | struct device_node *np = dev->of_node; | ||
204 | struct icn8318_data *data; | ||
205 | struct input_dev *input; | ||
206 | u32 fuzz_x = 0, fuzz_y = 0; | ||
207 | int error; | ||
208 | |||
209 | if (!client->irq) { | ||
210 | dev_err(dev, "Error no irq specified\n"); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
215 | if (!data) | ||
216 | return -ENOMEM; | ||
217 | |||
218 | data->wake_gpio = devm_gpiod_get(dev, "wake", GPIOD_OUT_LOW); | ||
219 | if (IS_ERR(data->wake_gpio)) { | ||
220 | error = PTR_ERR(data->wake_gpio); | ||
221 | if (error != -EPROBE_DEFER) | ||
222 | dev_err(dev, "Error getting wake gpio: %d\n", error); | ||
223 | return error; | ||
224 | } | ||
225 | |||
226 | if (of_property_read_u32(np, "touchscreen-size-x", &data->max_x) || | ||
227 | of_property_read_u32(np, "touchscreen-size-y", &data->max_y)) { | ||
228 | dev_err(dev, "Error touchscreen-size-x and/or -y missing\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | /* Optional */ | ||
233 | of_property_read_u32(np, "touchscreen-fuzz-x", &fuzz_x); | ||
234 | of_property_read_u32(np, "touchscreen-fuzz-y", &fuzz_y); | ||
235 | data->invert_x = of_property_read_bool(np, "touchscreen-inverted-x"); | ||
236 | data->invert_y = of_property_read_bool(np, "touchscreen-inverted-y"); | ||
237 | data->swap_x_y = of_property_read_bool(np, "touchscreen-swapped-x-y"); | ||
238 | |||
239 | input = devm_input_allocate_device(dev); | ||
240 | if (!input) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | input->name = client->name; | ||
244 | input->id.bustype = BUS_I2C; | ||
245 | input->open = icn8318_start; | ||
246 | input->close = icn8318_stop; | ||
247 | input->dev.parent = dev; | ||
248 | |||
249 | if (!data->swap_x_y) { | ||
250 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
251 | data->max_x, fuzz_x, 0); | ||
252 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
253 | data->max_y, fuzz_y, 0); | ||
254 | } else { | ||
255 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, | ||
256 | data->max_y, fuzz_y, 0); | ||
257 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, | ||
258 | data->max_x, fuzz_x, 0); | ||
259 | } | ||
260 | |||
261 | error = input_mt_init_slots(input, ICN8318_MAX_TOUCHES, | ||
262 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | ||
263 | if (error) | ||
264 | return error; | ||
265 | |||
266 | data->client = client; | ||
267 | data->input = input; | ||
268 | input_set_drvdata(input, data); | ||
269 | |||
270 | error = devm_request_threaded_irq(dev, client->irq, NULL, icn8318_irq, | ||
271 | IRQF_ONESHOT, client->name, data); | ||
272 | if (error) { | ||
273 | dev_err(dev, "Error requesting irq: %d\n", error); | ||
274 | return error; | ||
275 | } | ||
276 | |||
277 | /* Stop device till opened */ | ||
278 | icn8318_stop(data->input); | ||
279 | |||
280 | error = input_register_device(input); | ||
281 | if (error) | ||
282 | return error; | ||
283 | |||
284 | i2c_set_clientdata(client, data); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static const struct of_device_id icn8318_of_match[] = { | ||
290 | { .compatible = "chipone,icn8318" }, | ||
291 | { } | ||
292 | }; | ||
293 | MODULE_DEVICE_TABLE(of, icn8318_of_match); | ||
294 | |||
295 | /* This is useless for OF-enabled devices, but it is needed by I2C subsystem */ | ||
296 | static const struct i2c_device_id icn8318_i2c_id[] = { | ||
297 | { }, | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(i2c, icn8318_i2c_id); | ||
300 | |||
301 | static struct i2c_driver icn8318_driver = { | ||
302 | .driver = { | ||
303 | .owner = THIS_MODULE, | ||
304 | .name = "chipone_icn8318", | ||
305 | .pm = &icn8318_pm_ops, | ||
306 | .of_match_table = icn8318_of_match, | ||
307 | }, | ||
308 | .probe = icn8318_probe, | ||
309 | .id_table = icn8318_i2c_id, | ||
310 | }; | ||
311 | |||
312 | module_i2c_driver(icn8318_driver); | ||
313 | |||
314 | MODULE_DESCRIPTION("ChipOne icn8318 I2C Touchscreen Driver"); | ||
315 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
316 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index d4c24fb7704f..e6aef3e48bd9 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/gpio.h> | 37 | #include <linux/gpio.h> |
38 | #include <linux/of_gpio.h> | 38 | #include <linux/of_gpio.h> |
39 | #include <linux/input/mt.h> | 39 | #include <linux/input/mt.h> |
40 | #include <linux/input/touchscreen.h> | ||
40 | #include <linux/input/edt-ft5x06.h> | 41 | #include <linux/input/edt-ft5x06.h> |
41 | 42 | ||
42 | #define MAX_SUPPORT_POINTS 5 | 43 | #define MAX_SUPPORT_POINTS 5 |
@@ -1034,7 +1035,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
1034 | input->id.bustype = BUS_I2C; | 1035 | input->id.bustype = BUS_I2C; |
1035 | input->dev.parent = &client->dev; | 1036 | input->dev.parent = &client->dev; |
1036 | 1037 | ||
1037 | __set_bit(EV_SYN, input->evbit); | ||
1038 | __set_bit(EV_KEY, input->evbit); | 1038 | __set_bit(EV_KEY, input->evbit); |
1039 | __set_bit(EV_ABS, input->evbit); | 1039 | __set_bit(EV_ABS, input->evbit); |
1040 | __set_bit(BTN_TOUCH, input->keybit); | 1040 | __set_bit(BTN_TOUCH, input->keybit); |
@@ -1044,6 +1044,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, | |||
1044 | 0, tsdata->num_x * 64 - 1, 0, 0); | 1044 | 0, tsdata->num_x * 64 - 1, 0, 0); |
1045 | input_set_abs_params(input, ABS_MT_POSITION_Y, | 1045 | input_set_abs_params(input, ABS_MT_POSITION_Y, |
1046 | 0, tsdata->num_y * 64 - 1, 0, 0); | 1046 | 0, tsdata->num_y * 64 - 1, 0, 0); |
1047 | |||
1048 | if (!pdata) | ||
1049 | touchscreen_parse_of_params(input); | ||
1050 | |||
1047 | error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); | 1051 | error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0); |
1048 | if (error) { | 1052 | if (error) { |
1049 | dev_err(&client->dev, "Unable to init MT slots.\n"); | 1053 | dev_err(&client->dev, "Unable to init MT slots.\n"); |
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 926c58e540c0..43b3c9c2d788 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c | |||
@@ -98,7 +98,6 @@ | |||
98 | #define MAX_FW_UPDATE_RETRIES 30 | 98 | #define MAX_FW_UPDATE_RETRIES 30 |
99 | 99 | ||
100 | #define ELAN_FW_PAGESIZE 132 | 100 | #define ELAN_FW_PAGESIZE 132 |
101 | #define ELAN_FW_FILENAME "elants_i2c.bin" | ||
102 | 101 | ||
103 | /* calibration timeout definition */ | 102 | /* calibration timeout definition */ |
104 | #define ELAN_CALI_TIMEOUT_MSEC 10000 | 103 | #define ELAN_CALI_TIMEOUT_MSEC 10000 |
@@ -697,12 +696,19 @@ static int elants_i2c_fw_update(struct elants_data *ts) | |||
697 | { | 696 | { |
698 | struct i2c_client *client = ts->client; | 697 | struct i2c_client *client = ts->client; |
699 | const struct firmware *fw; | 698 | const struct firmware *fw; |
699 | char *fw_name; | ||
700 | int error; | 700 | int error; |
701 | 701 | ||
702 | error = request_firmware(&fw, ELAN_FW_FILENAME, &client->dev); | 702 | fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%4x.bin", ts->hw_version); |
703 | if (!fw_name) | ||
704 | return -ENOMEM; | ||
705 | |||
706 | dev_info(&client->dev, "requesting fw name = %s\n", fw_name); | ||
707 | error = request_firmware(&fw, fw_name, &client->dev); | ||
708 | kfree(fw_name); | ||
703 | if (error) { | 709 | if (error) { |
704 | dev_err(&client->dev, "failed to request firmware %s: %d\n", | 710 | dev_err(&client->dev, "failed to request firmware: %d\n", |
705 | ELAN_FW_FILENAME, error); | 711 | error); |
706 | return error; | 712 | return error; |
707 | } | 713 | } |
708 | 714 | ||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index ca196689f025..3af16984d57c 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/acpi.h> | ||
27 | #include <linux/of.h> | ||
26 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
27 | 29 | ||
28 | struct goodix_ts_data { | 30 | struct goodix_ts_data { |
@@ -48,6 +50,7 @@ struct goodix_ts_data { | |||
48 | #define GOODIX_REG_VERSION 0x8140 | 50 | #define GOODIX_REG_VERSION 0x8140 |
49 | 51 | ||
50 | #define RESOLUTION_LOC 1 | 52 | #define RESOLUTION_LOC 1 |
53 | #define MAX_CONTACTS_LOC 5 | ||
51 | #define TRIGGER_LOC 6 | 54 | #define TRIGGER_LOC 6 |
52 | 55 | ||
53 | static const unsigned long goodix_irq_flags[] = { | 56 | static const unsigned long goodix_irq_flags[] = { |
@@ -99,7 +102,7 @@ static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) | |||
99 | } | 102 | } |
100 | 103 | ||
101 | touch_num = data[0] & 0x0f; | 104 | touch_num = data[0] & 0x0f; |
102 | if (touch_num > GOODIX_MAX_CONTACTS) | 105 | if (touch_num > ts->max_touch_num) |
103 | return -EPROTO; | 106 | return -EPROTO; |
104 | 107 | ||
105 | if (touch_num > 1) { | 108 | if (touch_num > 1) { |
@@ -141,7 +144,7 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) | |||
141 | */ | 144 | */ |
142 | static void goodix_process_events(struct goodix_ts_data *ts) | 145 | static void goodix_process_events(struct goodix_ts_data *ts) |
143 | { | 146 | { |
144 | u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS]; | 147 | u8 point_data[1 + GOODIX_CONTACT_SIZE * ts->max_touch_num]; |
145 | int touch_num; | 148 | int touch_num; |
146 | int i; | 149 | int i; |
147 | 150 | ||
@@ -202,21 +205,23 @@ static void goodix_read_config(struct goodix_ts_data *ts) | |||
202 | ts->abs_x_max = GOODIX_MAX_WIDTH; | 205 | ts->abs_x_max = GOODIX_MAX_WIDTH; |
203 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | 206 | ts->abs_y_max = GOODIX_MAX_HEIGHT; |
204 | ts->int_trigger_type = GOODIX_INT_TRIGGER; | 207 | ts->int_trigger_type = GOODIX_INT_TRIGGER; |
208 | ts->max_touch_num = GOODIX_MAX_CONTACTS; | ||
205 | return; | 209 | return; |
206 | } | 210 | } |
207 | 211 | ||
208 | ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); | 212 | ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]); |
209 | ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); | 213 | ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]); |
210 | ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03; | 214 | ts->int_trigger_type = config[TRIGGER_LOC] & 0x03; |
211 | if (!ts->abs_x_max || !ts->abs_y_max) { | 215 | ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f; |
216 | if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) { | ||
212 | dev_err(&ts->client->dev, | 217 | dev_err(&ts->client->dev, |
213 | "Invalid config, using defaults\n"); | 218 | "Invalid config, using defaults\n"); |
214 | ts->abs_x_max = GOODIX_MAX_WIDTH; | 219 | ts->abs_x_max = GOODIX_MAX_WIDTH; |
215 | ts->abs_y_max = GOODIX_MAX_HEIGHT; | 220 | ts->abs_y_max = GOODIX_MAX_HEIGHT; |
221 | ts->max_touch_num = GOODIX_MAX_CONTACTS; | ||
216 | } | 222 | } |
217 | } | 223 | } |
218 | 224 | ||
219 | |||
220 | /** | 225 | /** |
221 | * goodix_read_version - Read goodix touchscreen version | 226 | * goodix_read_version - Read goodix touchscreen version |
222 | * | 227 | * |
@@ -295,7 +300,7 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) | |||
295 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); | 300 | input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); |
296 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); | 301 | input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); |
297 | 302 | ||
298 | input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS, | 303 | input_mt_init_slots(ts->input_dev, ts->max_touch_num, |
299 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); | 304 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
300 | 305 | ||
301 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; | 306 | ts->input_dev->name = "Goodix Capacitive TouchScreen"; |
@@ -372,11 +377,27 @@ static const struct i2c_device_id goodix_ts_id[] = { | |||
372 | { } | 377 | { } |
373 | }; | 378 | }; |
374 | 379 | ||
380 | #ifdef CONFIG_ACPI | ||
375 | static const struct acpi_device_id goodix_acpi_match[] = { | 381 | static const struct acpi_device_id goodix_acpi_match[] = { |
376 | { "GDIX1001", 0 }, | 382 | { "GDIX1001", 0 }, |
377 | { } | 383 | { } |
378 | }; | 384 | }; |
379 | MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); | 385 | MODULE_DEVICE_TABLE(acpi, goodix_acpi_match); |
386 | #endif | ||
387 | |||
388 | #ifdef CONFIG_OF | ||
389 | static const struct of_device_id goodix_of_match[] = { | ||
390 | { .compatible = "goodix,gt911" }, | ||
391 | { .compatible = "goodix,gt9110" }, | ||
392 | { .compatible = "goodix,gt912" }, | ||
393 | { .compatible = "goodix,gt927" }, | ||
394 | { .compatible = "goodix,gt9271" }, | ||
395 | { .compatible = "goodix,gt928" }, | ||
396 | { .compatible = "goodix,gt967" }, | ||
397 | { } | ||
398 | }; | ||
399 | MODULE_DEVICE_TABLE(of, goodix_of_match); | ||
400 | #endif | ||
380 | 401 | ||
381 | static struct i2c_driver goodix_ts_driver = { | 402 | static struct i2c_driver goodix_ts_driver = { |
382 | .probe = goodix_ts_probe, | 403 | .probe = goodix_ts_probe, |
@@ -384,7 +405,8 @@ static struct i2c_driver goodix_ts_driver = { | |||
384 | .driver = { | 405 | .driver = { |
385 | .name = "Goodix-TS", | 406 | .name = "Goodix-TS", |
386 | .owner = THIS_MODULE, | 407 | .owner = THIS_MODULE, |
387 | .acpi_match_table = goodix_acpi_match, | 408 | .acpi_match_table = ACPI_PTR(goodix_acpi_match), |
409 | .of_match_table = of_match_ptr(goodix_of_match), | ||
388 | }, | 410 | }, |
389 | }; | 411 | }; |
390 | module_i2c_driver(goodix_ts_driver); | 412 | module_i2c_driver(goodix_ts_driver); |
diff --git a/drivers/input/touchscreen/of_touchscreen.c b/drivers/input/touchscreen/of_touchscreen.c index f8f9b84230b1..b82b5207c78b 100644 --- a/drivers/input/touchscreen/of_touchscreen.c +++ b/drivers/input/touchscreen/of_touchscreen.c | |||
@@ -11,8 +11,41 @@ | |||
11 | 11 | ||
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/input.h> | 13 | #include <linux/input.h> |
14 | #include <linux/input/mt.h> | ||
14 | #include <linux/input/touchscreen.h> | 15 | #include <linux/input/touchscreen.h> |
15 | 16 | ||
17 | static u32 of_get_optional_u32(struct device_node *np, | ||
18 | const char *property) | ||
19 | { | ||
20 | u32 val = 0; | ||
21 | |||
22 | of_property_read_u32(np, property, &val); | ||
23 | |||
24 | return val; | ||
25 | } | ||
26 | |||
27 | static void touchscreen_set_params(struct input_dev *dev, | ||
28 | unsigned long axis, | ||
29 | int max, int fuzz) | ||
30 | { | ||
31 | struct input_absinfo *absinfo; | ||
32 | |||
33 | if (!test_bit(axis, dev->absbit)) { | ||
34 | /* | ||
35 | * Emit a warning only if the axis is not a multitouch | ||
36 | * axis, which might not be set by the driver. | ||
37 | */ | ||
38 | if (!input_is_mt_axis(axis)) | ||
39 | dev_warn(&dev->dev, | ||
40 | "DT specifies parameters but the axis is not set up\n"); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | absinfo = &dev->absinfo[axis]; | ||
45 | absinfo->maximum = max; | ||
46 | absinfo->fuzz = fuzz; | ||
47 | } | ||
48 | |||
16 | /** | 49 | /** |
17 | * touchscreen_parse_of_params - parse common touchscreen DT properties | 50 | * touchscreen_parse_of_params - parse common touchscreen DT properties |
18 | * @dev: device that should be parsed | 51 | * @dev: device that should be parsed |
@@ -24,22 +57,31 @@ | |||
24 | void touchscreen_parse_of_params(struct input_dev *dev) | 57 | void touchscreen_parse_of_params(struct input_dev *dev) |
25 | { | 58 | { |
26 | struct device_node *np = dev->dev.parent->of_node; | 59 | struct device_node *np = dev->dev.parent->of_node; |
27 | struct input_absinfo *absinfo; | 60 | u32 maximum, fuzz; |
28 | 61 | ||
29 | input_alloc_absinfo(dev); | 62 | input_alloc_absinfo(dev); |
30 | if (!dev->absinfo) | 63 | if (!dev->absinfo) |
31 | return; | 64 | return; |
32 | 65 | ||
33 | absinfo = &dev->absinfo[ABS_X]; | 66 | maximum = of_get_optional_u32(np, "touchscreen-size-x"); |
34 | of_property_read_u32(np, "touchscreen-size-x", &absinfo->maximum); | 67 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-x"); |
35 | of_property_read_u32(np, "touchscreen-fuzz-x", &absinfo->fuzz); | 68 | if (maximum || fuzz) { |
69 | touchscreen_set_params(dev, ABS_X, maximum, fuzz); | ||
70 | touchscreen_set_params(dev, ABS_MT_POSITION_X, maximum, fuzz); | ||
71 | } | ||
36 | 72 | ||
37 | absinfo = &dev->absinfo[ABS_Y]; | 73 | maximum = of_get_optional_u32(np, "touchscreen-size-y"); |
38 | of_property_read_u32(np, "touchscreen-size-y", &absinfo->maximum); | 74 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-y"); |
39 | of_property_read_u32(np, "touchscreen-fuzz-y", &absinfo->fuzz); | 75 | if (maximum || fuzz) { |
76 | touchscreen_set_params(dev, ABS_Y, maximum, fuzz); | ||
77 | touchscreen_set_params(dev, ABS_MT_POSITION_Y, maximum, fuzz); | ||
78 | } | ||
40 | 79 | ||
41 | absinfo = &dev->absinfo[ABS_PRESSURE]; | 80 | maximum = of_get_optional_u32(np, "touchscreen-max-pressure"); |
42 | of_property_read_u32(np, "touchscreen-max-pressure", &absinfo->maximum); | 81 | fuzz = of_get_optional_u32(np, "touchscreen-fuzz-pressure"); |
43 | of_property_read_u32(np, "touchscreen-fuzz-pressure", &absinfo->fuzz); | 82 | if (maximum || fuzz) { |
83 | touchscreen_set_params(dev, ABS_PRESSURE, maximum, fuzz); | ||
84 | touchscreen_set_params(dev, ABS_MT_PRESSURE, maximum, fuzz); | ||
85 | } | ||
44 | } | 86 | } |
45 | EXPORT_SYMBOL(touchscreen_parse_of_params); | 87 | EXPORT_SYMBOL(touchscreen_parse_of_params); |
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index b93a28b955fd..c0116994067d 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c | |||
@@ -30,6 +30,10 @@ | |||
30 | * These kinds of heuristics are just asking for trouble (and don't belong | 30 | * These kinds of heuristics are just asking for trouble (and don't belong |
31 | * in the kernel). So this driver offers straight forward, reliable single | 31 | * in the kernel). So this driver offers straight forward, reliable single |
32 | * touch functionality only. | 32 | * touch functionality only. |
33 | * | ||
34 | * s.a. A20 User Manual "1.15 TP" (Documentation/arm/sunxi/README) | ||
35 | * (looks like the description in the A20 User Manual v1.3 is better | ||
36 | * than the one in the A10 User Manual v.1.5) | ||
33 | */ | 37 | */ |
34 | 38 | ||
35 | #include <linux/err.h> | 39 | #include <linux/err.h> |
@@ -193,7 +197,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, long *temp) | |||
193 | if (ts->temp_data == -1) | 197 | if (ts->temp_data == -1) |
194 | return -EAGAIN; | 198 | return -EAGAIN; |
195 | 199 | ||
196 | *temp = (ts->temp_data - ts->temp_offset) * ts->temp_step; | 200 | *temp = ts->temp_data * ts->temp_step - ts->temp_offset; |
197 | 201 | ||
198 | return 0; | 202 | return 0; |
199 | } | 203 | } |
@@ -246,6 +250,8 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
246 | int error; | 250 | int error; |
247 | u32 reg; | 251 | u32 reg; |
248 | bool ts_attached; | 252 | bool ts_attached; |
253 | u32 tp_sensitive_adjust = 15; | ||
254 | u32 filter_type = 1; | ||
249 | 255 | ||
250 | ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); | 256 | ts = devm_kzalloc(dev, sizeof(struct sun4i_ts_data), GFP_KERNEL); |
251 | if (!ts) | 257 | if (!ts) |
@@ -255,22 +261,31 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
255 | ts->ignore_fifo_data = true; | 261 | ts->ignore_fifo_data = true; |
256 | ts->temp_data = -1; | 262 | ts->temp_data = -1; |
257 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { | 263 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) { |
258 | /* Allwinner SDK has temperature = -271 + (value / 6) (C) */ | 264 | /* Allwinner SDK has temperature (C) = (value / 6) - 271 */ |
259 | ts->temp_offset = 1626; | 265 | ts->temp_offset = 271000; |
260 | ts->temp_step = 167; | 266 | ts->temp_step = 167; |
267 | } else if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) { | ||
268 | /* | ||
269 | * The A10 temperature sensor has quite a wide spread, these | ||
270 | * parameters are based on the averaging of the calibration | ||
271 | * results of 4 completely different boards, with a spread of | ||
272 | * temp_step from 0.096 - 0.170 and temp_offset from 176 - 331. | ||
273 | */ | ||
274 | ts->temp_offset = 257000; | ||
275 | ts->temp_step = 133; | ||
261 | } else { | 276 | } else { |
262 | /* | 277 | /* |
263 | * The user manuals do not contain the formula for calculating | 278 | * The user manuals do not contain the formula for calculating |
264 | * the temperature. The formula used here is from the AXP209, | 279 | * the temperature. The formula used here is from the AXP209, |
265 | * which is designed by X-Powers, an affiliate of Allwinner: | 280 | * which is designed by X-Powers, an affiliate of Allwinner: |
266 | * | 281 | * |
267 | * temperature = -144.7 + (value * 0.1) | 282 | * temperature (C) = (value * 0.1) - 144.7 |
268 | * | 283 | * |
269 | * Allwinner does not have any documentation whatsoever for | 284 | * Allwinner does not have any documentation whatsoever for |
270 | * this hardware. Moreover, it is claimed that the sensor | 285 | * this hardware. Moreover, it is claimed that the sensor |
271 | * is inaccurate and cannot work properly. | 286 | * is inaccurate and cannot work properly. |
272 | */ | 287 | */ |
273 | ts->temp_offset = 1447; | 288 | ts->temp_offset = 144700; |
274 | ts->temp_step = 100; | 289 | ts->temp_step = 100; |
275 | } | 290 | } |
276 | 291 | ||
@@ -313,14 +328,20 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
313 | ts->base + TP_CTRL0); | 328 | ts->base + TP_CTRL0); |
314 | 329 | ||
315 | /* | 330 | /* |
316 | * sensitive_adjust = 15 : max, which is not all that sensitive, | 331 | * tp_sensitive_adjust is an optional property |
317 | * tp_mode = 0 : only x and y coordinates, as we don't use dual touch | 332 | * tp_mode = 0 : only x and y coordinates, as we don't use dual touch |
318 | */ | 333 | */ |
319 | writel(TP_SENSITIVE_ADJUST(15) | TP_MODE_SELECT(0), | 334 | of_property_read_u32(np, "allwinner,tp-sensitive-adjust", |
335 | &tp_sensitive_adjust); | ||
336 | writel(TP_SENSITIVE_ADJUST(tp_sensitive_adjust) | TP_MODE_SELECT(0), | ||
320 | ts->base + TP_CTRL2); | 337 | ts->base + TP_CTRL2); |
321 | 338 | ||
322 | /* Enable median filter, type 1 : 5/3 */ | 339 | /* |
323 | writel(FILTER_EN(1) | FILTER_TYPE(1), ts->base + TP_CTRL3); | 340 | * Enable median and averaging filter, optional property for |
341 | * filter type. | ||
342 | */ | ||
343 | of_property_read_u32(np, "allwinner,filter-type", &filter_type); | ||
344 | writel(FILTER_EN(1) | FILTER_TYPE(filter_type), ts->base + TP_CTRL3); | ||
324 | 345 | ||
325 | /* Enable temperature measurement, period 1953 (2 seconds) */ | 346 | /* Enable temperature measurement, period 1953 (2 seconds) */ |
326 | writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); | 347 | writel(TEMP_ENABLE(1) | TEMP_PERIOD(1953), ts->base + TP_TPR); |
@@ -330,10 +351,10 @@ static int sun4i_ts_probe(struct platform_device *pdev) | |||
330 | * finally enable tp mode. | 351 | * finally enable tp mode. |
331 | */ | 352 | */ |
332 | reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); | 353 | reg = STYLUS_UP_DEBOUN(5) | STYLUS_UP_DEBOUN_EN(1); |
333 | if (of_device_is_compatible(np, "allwinner,sun4i-a10-ts")) | 354 | if (of_device_is_compatible(np, "allwinner,sun6i-a31-ts")) |
334 | reg |= TP_MODE_EN(1); | ||
335 | else | ||
336 | reg |= SUN6I_TP_MODE_EN(1); | 355 | reg |= SUN6I_TP_MODE_EN(1); |
356 | else | ||
357 | reg |= TP_MODE_EN(1); | ||
337 | writel(reg, ts->base + TP_CTRL1); | 358 | writel(reg, ts->base + TP_CTRL1); |
338 | 359 | ||
339 | /* | 360 | /* |
@@ -383,6 +404,7 @@ static int sun4i_ts_remove(struct platform_device *pdev) | |||
383 | 404 | ||
384 | static const struct of_device_id sun4i_ts_of_match[] = { | 405 | static const struct of_device_id sun4i_ts_of_match[] = { |
385 | { .compatible = "allwinner,sun4i-a10-ts", }, | 406 | { .compatible = "allwinner,sun4i-a10-ts", }, |
407 | { .compatible = "allwinner,sun5i-a13-ts", }, | ||
386 | { .compatible = "allwinner,sun6i-a31-ts", }, | 408 | { .compatible = "allwinner,sun6i-a31-ts", }, |
387 | { /* sentinel */ } | 409 | { /* sentinel */ } |
388 | }; | 410 | }; |
diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c new file mode 100644 index 000000000000..aecb9ad2e701 --- /dev/null +++ b/drivers/input/touchscreen/sx8654.c | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Driver for Semtech SX8654 I2C touchscreen controller. | ||
3 | * | ||
4 | * Copyright (c) 2015 Armadeus Systems | ||
5 | * Sébastien Szymanski <sebastien.szymanski@armadeus.com> | ||
6 | * | ||
7 | * Using code from: | ||
8 | * - sx865x.c | ||
9 | * Copyright (c) 2013 U-MoBo Srl | ||
10 | * Pierluigi Passaro <p.passaro@u-mobo.com> | ||
11 | * - sx8650.c | ||
12 | * Copyright (c) 2009 Wayne Roberts | ||
13 | * - tsc2007.c | ||
14 | * Copyright (c) 2008 Kwangwoo Lee | ||
15 | * - ads7846.c | ||
16 | * Copyright (c) 2005 David Brownell | ||
17 | * Copyright (c) 2006 Nokia Corporation | ||
18 | * - corgi_ts.c | ||
19 | * Copyright (C) 2004-2005 Richard Purdie | ||
20 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
21 | * Copyright (C) 2002 MontaVista Software | ||
22 | * Copyright (C) 2004 Texas Instruments | ||
23 | * Copyright (C) 2005 Dirk Behme | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or modify | ||
26 | * it under the terms of the GNU General Public License version 2 as | ||
27 | * published by the Free Software Foundation. | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/of.h> | ||
33 | #include <linux/i2c.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/irq.h> | ||
36 | |||
37 | /* register addresses */ | ||
38 | #define I2C_REG_TOUCH0 0x00 | ||
39 | #define I2C_REG_TOUCH1 0x01 | ||
40 | #define I2C_REG_CHANMASK 0x04 | ||
41 | #define I2C_REG_IRQMASK 0x22 | ||
42 | #define I2C_REG_IRQSRC 0x23 | ||
43 | #define I2C_REG_SOFTRESET 0x3f | ||
44 | |||
45 | /* commands */ | ||
46 | #define CMD_READ_REGISTER 0x40 | ||
47 | #define CMD_MANUAL 0xc0 | ||
48 | #define CMD_PENTRG 0xe0 | ||
49 | |||
50 | /* value for I2C_REG_SOFTRESET */ | ||
51 | #define SOFTRESET_VALUE 0xde | ||
52 | |||
53 | /* bits for I2C_REG_IRQSRC */ | ||
54 | #define IRQ_PENTOUCH_TOUCHCONVDONE 0x08 | ||
55 | #define IRQ_PENRELEASE 0x04 | ||
56 | |||
57 | /* bits for RegTouch1 */ | ||
58 | #define CONDIRQ 0x20 | ||
59 | #define FILT_7SA 0x03 | ||
60 | |||
61 | /* bits for I2C_REG_CHANMASK */ | ||
62 | #define CONV_X 0x80 | ||
63 | #define CONV_Y 0x40 | ||
64 | |||
65 | /* coordinates rate: higher nibble of CTRL0 register */ | ||
66 | #define RATE_MANUAL 0x00 | ||
67 | #define RATE_5000CPS 0xf0 | ||
68 | |||
69 | /* power delay: lower nibble of CTRL0 register */ | ||
70 | #define POWDLY_1_1MS 0x0b | ||
71 | |||
72 | #define MAX_12BIT ((1 << 12) - 1) | ||
73 | |||
74 | struct sx8654 { | ||
75 | struct input_dev *input; | ||
76 | struct i2c_client *client; | ||
77 | }; | ||
78 | |||
79 | static irqreturn_t sx8654_irq(int irq, void *handle) | ||
80 | { | ||
81 | struct sx8654 *sx8654 = handle; | ||
82 | int irqsrc; | ||
83 | u8 data[4]; | ||
84 | unsigned int x, y; | ||
85 | int retval; | ||
86 | |||
87 | irqsrc = i2c_smbus_read_byte_data(sx8654->client, | ||
88 | CMD_READ_REGISTER | I2C_REG_IRQSRC); | ||
89 | dev_dbg(&sx8654->client->dev, "irqsrc = 0x%x", irqsrc); | ||
90 | |||
91 | if (irqsrc < 0) | ||
92 | goto out; | ||
93 | |||
94 | if (irqsrc & IRQ_PENRELEASE) { | ||
95 | dev_dbg(&sx8654->client->dev, "pen release interrupt"); | ||
96 | |||
97 | input_report_key(sx8654->input, BTN_TOUCH, 0); | ||
98 | input_sync(sx8654->input); | ||
99 | } | ||
100 | |||
101 | if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) { | ||
102 | dev_dbg(&sx8654->client->dev, "pen touch interrupt"); | ||
103 | |||
104 | retval = i2c_master_recv(sx8654->client, data, sizeof(data)); | ||
105 | if (retval != sizeof(data)) | ||
106 | goto out; | ||
107 | |||
108 | /* invalid data */ | ||
109 | if (unlikely(data[0] & 0x80 || data[2] & 0x80)) | ||
110 | goto out; | ||
111 | |||
112 | x = ((data[0] & 0xf) << 8) | (data[1]); | ||
113 | y = ((data[2] & 0xf) << 8) | (data[3]); | ||
114 | |||
115 | input_report_abs(sx8654->input, ABS_X, x); | ||
116 | input_report_abs(sx8654->input, ABS_Y, y); | ||
117 | input_report_key(sx8654->input, BTN_TOUCH, 1); | ||
118 | input_sync(sx8654->input); | ||
119 | |||
120 | dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y); | ||
121 | } | ||
122 | |||
123 | out: | ||
124 | return IRQ_HANDLED; | ||
125 | } | ||
126 | |||
127 | static int sx8654_open(struct input_dev *dev) | ||
128 | { | ||
129 | struct sx8654 *sx8654 = input_get_drvdata(dev); | ||
130 | struct i2c_client *client = sx8654->client; | ||
131 | int error; | ||
132 | |||
133 | /* enable pen trigger mode */ | ||
134 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, | ||
135 | RATE_5000CPS | POWDLY_1_1MS); | ||
136 | if (error) { | ||
137 | dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); | ||
138 | return error; | ||
139 | } | ||
140 | |||
141 | error = i2c_smbus_write_byte(client, CMD_PENTRG); | ||
142 | if (error) { | ||
143 | dev_err(&client->dev, "writing command CMD_PENTRG failed"); | ||
144 | return error; | ||
145 | } | ||
146 | |||
147 | enable_irq(client->irq); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static void sx8654_close(struct input_dev *dev) | ||
153 | { | ||
154 | struct sx8654 *sx8654 = input_get_drvdata(dev); | ||
155 | struct i2c_client *client = sx8654->client; | ||
156 | int error; | ||
157 | |||
158 | disable_irq(client->irq); | ||
159 | |||
160 | /* enable manual mode mode */ | ||
161 | error = i2c_smbus_write_byte(client, CMD_MANUAL); | ||
162 | if (error) { | ||
163 | dev_err(&client->dev, "writing command CMD_MANUAL failed"); | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, 0); | ||
168 | if (error) { | ||
169 | dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed"); | ||
170 | return; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static int sx8654_probe(struct i2c_client *client, | ||
175 | const struct i2c_device_id *id) | ||
176 | { | ||
177 | struct sx8654 *sx8654; | ||
178 | struct input_dev *input; | ||
179 | int error; | ||
180 | |||
181 | if (!i2c_check_functionality(client->adapter, | ||
182 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | ||
183 | return -ENXIO; | ||
184 | |||
185 | sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL); | ||
186 | if (!sx8654) | ||
187 | return -ENOMEM; | ||
188 | |||
189 | input = devm_input_allocate_device(&client->dev); | ||
190 | if (!sx8654) | ||
191 | return -ENOMEM; | ||
192 | |||
193 | input->name = "SX8654 I2C Touchscreen"; | ||
194 | input->id.bustype = BUS_I2C; | ||
195 | input->dev.parent = &client->dev; | ||
196 | input->open = sx8654_open; | ||
197 | input->close = sx8654_close; | ||
198 | |||
199 | __set_bit(INPUT_PROP_DIRECT, input->propbit); | ||
200 | input_set_capability(input, EV_KEY, BTN_TOUCH); | ||
201 | input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0); | ||
202 | input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0); | ||
203 | |||
204 | sx8654->client = client; | ||
205 | sx8654->input = input; | ||
206 | |||
207 | input_set_drvdata(sx8654->input, sx8654); | ||
208 | |||
209 | error = i2c_smbus_write_byte_data(client, I2C_REG_SOFTRESET, | ||
210 | SOFTRESET_VALUE); | ||
211 | if (error) { | ||
212 | dev_err(&client->dev, "writing softreset value failed"); | ||
213 | return error; | ||
214 | } | ||
215 | |||
216 | error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK, | ||
217 | CONV_X | CONV_Y); | ||
218 | if (error) { | ||
219 | dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed"); | ||
220 | return error; | ||
221 | } | ||
222 | |||
223 | error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK, | ||
224 | IRQ_PENTOUCH_TOUCHCONVDONE | | ||
225 | IRQ_PENRELEASE); | ||
226 | if (error) { | ||
227 | dev_err(&client->dev, "writing to I2C_REG_IRQMASK failed"); | ||
228 | return error; | ||
229 | } | ||
230 | |||
231 | error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1, | ||
232 | CONDIRQ | FILT_7SA); | ||
233 | if (error) { | ||
234 | dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed"); | ||
235 | return error; | ||
236 | } | ||
237 | |||
238 | error = devm_request_threaded_irq(&client->dev, client->irq, | ||
239 | NULL, sx8654_irq, | ||
240 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
241 | client->name, sx8654); | ||
242 | if (error) { | ||
243 | dev_err(&client->dev, | ||
244 | "Failed to enable IRQ %d, error: %d\n", | ||
245 | client->irq, error); | ||
246 | return error; | ||
247 | } | ||
248 | |||
249 | /* Disable the IRQ, we'll enable it in sx8654_open() */ | ||
250 | disable_irq(client->irq); | ||
251 | |||
252 | error = input_register_device(sx8654->input); | ||
253 | if (error) | ||
254 | return error; | ||
255 | |||
256 | i2c_set_clientdata(client, sx8654); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | #ifdef CONFIG_OF | ||
261 | static const struct of_device_id sx8654_of_match[] = { | ||
262 | { .compatible = "semtech,sx8654", }, | ||
263 | { }, | ||
264 | }; | ||
265 | MODULE_DEVICE_TABLE(of, sx8654_of_match); | ||
266 | #endif | ||
267 | |||
268 | static const struct i2c_device_id sx8654_id_table[] = { | ||
269 | { "semtech_sx8654", 0 }, | ||
270 | { }, | ||
271 | }; | ||
272 | MODULE_DEVICE_TABLE(i2c, sx8654_id_table); | ||
273 | |||
274 | static struct i2c_driver sx8654_driver = { | ||
275 | .driver = { | ||
276 | .name = "sx8654", | ||
277 | .of_match_table = of_match_ptr(sx8654_of_match), | ||
278 | }, | ||
279 | .id_table = sx8654_id_table, | ||
280 | .probe = sx8654_probe, | ||
281 | }; | ||
282 | module_i2c_driver(sx8654_driver); | ||
283 | |||
284 | MODULE_AUTHOR("Sébastien Szymanski <sebastien.szymanski@armadeus.com>"); | ||
285 | MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver"); | ||
286 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 1bf9906b5a3f..ccc8aa615709 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -75,7 +75,7 @@ struct tsc2007 { | |||
75 | u16 model; | 75 | u16 model; |
76 | u16 x_plate_ohms; | 76 | u16 x_plate_ohms; |
77 | u16 max_rt; | 77 | u16 max_rt; |
78 | unsigned long poll_period; | 78 | unsigned long poll_period; /* in jiffies */ |
79 | int fuzzx; | 79 | int fuzzx; |
80 | int fuzzy; | 80 | int fuzzy; |
81 | int fuzzz; | 81 | int fuzzz; |
@@ -214,8 +214,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) | |||
214 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 214 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
215 | } | 215 | } |
216 | 216 | ||
217 | wait_event_timeout(ts->wait, ts->stopped, | 217 | wait_event_timeout(ts->wait, ts->stopped, ts->poll_period); |
218 | msecs_to_jiffies(ts->poll_period)); | ||
219 | } | 218 | } |
220 | 219 | ||
221 | dev_dbg(&ts->client->dev, "UP\n"); | 220 | dev_dbg(&ts->client->dev, "UP\n"); |
@@ -314,9 +313,9 @@ static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts) | |||
314 | ts->fuzzz = val32; | 313 | ts->fuzzz = val32; |
315 | 314 | ||
316 | if (!of_property_read_u64(np, "ti,poll-period", &val64)) | 315 | if (!of_property_read_u64(np, "ti,poll-period", &val64)) |
317 | ts->poll_period = val64; | 316 | ts->poll_period = msecs_to_jiffies(val64); |
318 | else | 317 | else |
319 | ts->poll_period = 1; | 318 | ts->poll_period = msecs_to_jiffies(1); |
320 | 319 | ||
321 | if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { | 320 | if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) { |
322 | ts->x_plate_ohms = val32; | 321 | ts->x_plate_ohms = val32; |
@@ -350,7 +349,7 @@ static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts, | |||
350 | ts->model = pdata->model; | 349 | ts->model = pdata->model; |
351 | ts->x_plate_ohms = pdata->x_plate_ohms; | 350 | ts->x_plate_ohms = pdata->x_plate_ohms; |
352 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; | 351 | ts->max_rt = pdata->max_rt ? : MAX_12BIT; |
353 | ts->poll_period = pdata->poll_period ? : 1; | 352 | ts->poll_period = msecs_to_jiffies(pdata->poll_period ? : 1); |
354 | ts->get_pendown_state = pdata->get_pendown_state; | 353 | ts->get_pendown_state = pdata->get_pendown_state; |
355 | ts->clear_penirq = pdata->clear_penirq; | 354 | ts->clear_penirq = pdata->clear_penirq; |
356 | ts->fuzzx = pdata->fuzzx; | 355 | ts->fuzzx = pdata->fuzzx; |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index a0966331a89b..f2c6c352c55a 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -132,6 +132,7 @@ enum { | |||
132 | DEVTYPE_GUNZE, | 132 | DEVTYPE_GUNZE, |
133 | DEVTYPE_DMC_TSC10, | 133 | DEVTYPE_DMC_TSC10, |
134 | DEVTYPE_IRTOUCH, | 134 | DEVTYPE_IRTOUCH, |
135 | DEVTYPE_IRTOUCH_HIRES, | ||
135 | DEVTYPE_IDEALTEK, | 136 | DEVTYPE_IDEALTEK, |
136 | DEVTYPE_GENERAL_TOUCH, | 137 | DEVTYPE_GENERAL_TOUCH, |
137 | DEVTYPE_GOTOP, | 138 | DEVTYPE_GOTOP, |
@@ -198,6 +199,7 @@ static const struct usb_device_id usbtouch_devices[] = { | |||
198 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH | 199 | #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH |
199 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 200 | {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
200 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, | 201 | {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, |
202 | {USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES}, | ||
201 | #endif | 203 | #endif |
202 | 204 | ||
203 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 205 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK |
@@ -1177,6 +1179,15 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1177 | .rept_size = 8, | 1179 | .rept_size = 8, |
1178 | .read_data = irtouch_read_data, | 1180 | .read_data = irtouch_read_data, |
1179 | }, | 1181 | }, |
1182 | |||
1183 | [DEVTYPE_IRTOUCH_HIRES] = { | ||
1184 | .min_xc = 0x0, | ||
1185 | .max_xc = 0x7fff, | ||
1186 | .min_yc = 0x0, | ||
1187 | .max_yc = 0x7fff, | ||
1188 | .rept_size = 8, | ||
1189 | .read_data = irtouch_read_data, | ||
1190 | }, | ||
1180 | #endif | 1191 | #endif |
1181 | 1192 | ||
1182 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK | 1193 | #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK |