blob: cfa6170b35aa06c17d8f0054ab1f2a5aaad66cb6 [file] [log] [blame]
Arve Hjønnevågc3fffcb2008-10-15 18:23:47 -07001/* drivers/input/misc/gpio_matrix.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
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
16#include <linux/kernel.h>
17#include <linux/gpio.h>
18#include <linux/gpio_event.h>
19#include <linux/hrtimer.h>
20#include <linux/interrupt.h>
21#include <linux/slab.h>
22#include <linux/wakelock.h>
Flemmardc36b8672013-10-23 17:43:54 +020023#ifdef CONFIG_OPTICALJOYSTICK_CRUCIAL
24#include <asm/mach-types.h>
25#include <linux/curcial_oj.h>
26#endif
Arve Hjønnevågc3fffcb2008-10-15 18:23:47 -070027
28struct gpio_kp {
29 struct gpio_event_input_devs *input_devs;
30 struct gpio_event_matrix_info *keypad_info;
31 struct hrtimer timer;
32 struct wake_lock wake_lock;
33 int current_output;
34 unsigned int use_irq:1;
35 unsigned int key_state_changed:1;
36 unsigned int last_key_state_changed:1;
37 unsigned int some_keys_pressed:2;
38 unsigned int disabled_irq:1;
39 unsigned long keys_pressed[0];
40};
41
42static void clear_phantom_key(struct gpio_kp *kp, int out, int in)
43{
44 struct gpio_event_matrix_info *mi = kp->keypad_info;
45 int key_index = out * mi->ninputs + in;
46 unsigned short keyentry = mi->keymap[key_index];
47 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
48 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
49
50 if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) {
51 if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
52 pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
53 "cleared\n", keycode, out, in,
54 mi->output_gpios[out], mi->input_gpios[in]);
55 __clear_bit(key_index, kp->keys_pressed);
56 } else {
57 if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
58 pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
59 "not cleared\n", keycode, out, in,
60 mi->output_gpios[out], mi->input_gpios[in]);
61 }
62}
63
64static int restore_keys_for_input(struct gpio_kp *kp, int out, int in)
65{
66 int rv = 0;
67 int key_index;
68
69 key_index = out * kp->keypad_info->ninputs + in;
70 while (out < kp->keypad_info->noutputs) {
71 if (test_bit(key_index, kp->keys_pressed)) {
72 rv = 1;
73 clear_phantom_key(kp, out, in);
74 }
75 key_index += kp->keypad_info->ninputs;
76 out++;
77 }
78 return rv;
79}
80
81static void remove_phantom_keys(struct gpio_kp *kp)
82{
83 int out, in, inp;
84 int key_index;
85
86 if (kp->some_keys_pressed < 3)
87 return;
88
89 for (out = 0; out < kp->keypad_info->noutputs; out++) {
90 inp = -1;
91 key_index = out * kp->keypad_info->ninputs;
92 for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) {
93 if (test_bit(key_index, kp->keys_pressed)) {
94 if (inp == -1) {
95 inp = in;
96 continue;
97 }
98 if (inp >= 0) {
99 if (!restore_keys_for_input(kp, out + 1,
100 inp))
101 break;
102 clear_phantom_key(kp, out, inp);
103 inp = -2;
104 }
105 restore_keys_for_input(kp, out, in);
106 }
107 }
108 }
109}
110
111static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
112{
113 struct gpio_event_matrix_info *mi = kp->keypad_info;
114 int pressed = test_bit(key_index, kp->keys_pressed);
115 unsigned short keyentry = mi->keymap[key_index];
116 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
117 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
Flemmardc36b8672013-10-23 17:43:54 +0200118#ifdef CONFIG_OPTICALJOYSTICK_CRUCIAL
119 static unsigned need_send_spec_key = 1;
120#endif
Arve Hjønnevågc3fffcb2008-10-15 18:23:47 -0700121
122 if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) {
123 if (keycode == KEY_RESERVED) {
124 if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
125 pr_info("gpiomatrix: unmapped key, %d-%d "
126 "(%d-%d) changed to %d\n",
127 out, in, mi->output_gpios[out],
128 mi->input_gpios[in], pressed);
129 } else {
130 if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS)
131 pr_info("gpiomatrix: key %x, %d-%d (%d-%d) "
132 "changed to %d\n", keycode,
133 out, in, mi->output_gpios[out],
134 mi->input_gpios[in], pressed);
Flemmardc36b8672013-10-23 17:43:54 +0200135#ifdef CONFIG_OPTICALJOYSTICK_CRUCIAL
136 if (!(mi->info.oj_btn && keycode == BTN_MOUSE))
137#endif
Arve Hjønnevågc3fffcb2008-10-15 18:23:47 -0700138 input_report_key(kp->input_devs->dev[dev], keycode, pressed);
139 }
140 }
Flemmardc36b8672013-10-23 17:43:54 +0200141#ifdef CONFIG_OPTICALJOYSTICK_CRUCIAL
142 if (mi->info.oj_btn && keycode == BTN_MOUSE) {
143 if (need_send_spec_key == pressed) {
144 curcial_oj_send_key(keycode, pressed);
145 need_send_spec_key = !pressed;
146 pr_info("%s: send OJ action key, pressed: %d\n",
147 __func__, pressed);
148 }
149 }
150#endif
Arve Hjønnevågc3fffcb2008-10-15 18:23:47 -0700151}
152
153static void report_sync(struct gpio_kp *kp)
154{
155 int i;
156
157 for (i = 0; i < kp->input_devs->count; i++)
158 input_sync(kp->input_devs->dev[i]);
159}
160
161static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
162{
163 int out, in;
164 int key_index;
165 int gpio;
166 struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer);
167 struct gpio_event_matrix_info *mi = kp->keypad_info;
168 unsigned gpio_keypad_flags = mi->flags;
169 unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH);
170
171 out = kp->current_output;
172 if (out == mi->noutputs) {
173 out = 0;
174 kp->last_key_state_changed = kp->key_state_changed;
175 kp->key_state_changed = 0;
176 kp->some_keys_pressed = 0;
177 } else {
178 key_index = out * mi->ninputs;
179 for (in = 0; in < mi->ninputs; in++, key_index++) {
180 gpio = mi->input_gpios[in];
181 if (gpio_get_value(gpio) ^ !polarity) {
182 if (kp->some_keys_pressed < 3)
183 kp->some_keys_pressed++;
184 kp->key_state_changed |= !__test_and_set_bit(
185 key_index, kp->keys_pressed);
186 } else
187 kp->key_state_changed |= __test_and_clear_bit(
188 key_index, kp->keys_pressed);
189 }
190 gpio = mi->output_gpios[out];
191 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
192 gpio_set_value(gpio, !polarity);
193 else
194 gpio_direction_input(gpio);
195 out++;
196 }
197 kp->current_output = out;
198 if (out < mi->noutputs) {
199 gpio = mi->output_gpios[out];
200 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
201 gpio_set_value(gpio, polarity);
202 else
203 gpio_direction_output(gpio, polarity);
204 hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL);
205 return HRTIMER_NORESTART;
206 }
207 if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) {
208 if (kp->key_state_changed) {
209 hrtimer_start(&kp->timer, mi->debounce_delay,
210 HRTIMER_MODE_REL);
211 return HRTIMER_NORESTART;
212 }
213 kp->key_state_changed = kp->last_key_state_changed;
214 }
215 if (kp->key_state_changed) {
216 if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS)
217 remove_phantom_keys(kp);
218 key_index = 0;
219 for (out = 0; out < mi->noutputs; out++)
220 for (in = 0; in < mi->ninputs; in++, key_index++)
221 report_key(kp, key_index, out, in);
222 report_sync(kp);
223 }
224 if (!kp->use_irq || kp->some_keys_pressed) {
225 hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL);
226 return HRTIMER_NORESTART;
227 }
228
229 /* No keys are pressed, reenable interrupt */
230 for (out = 0; out < mi->noutputs; out++) {
231 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
232 gpio_set_value(mi->output_gpios[out], polarity);
233 else
234 gpio_direction_output(mi->output_gpios[out], polarity);
235 }
236 for (in = 0; in < mi->ninputs; in++)
237 enable_irq(gpio_to_irq(mi->input_gpios[in]));
238 wake_unlock(&kp->wake_lock);
239 return HRTIMER_NORESTART;
240}
241
242static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
243{
244 int i;
245 struct gpio_kp *kp = dev_id;
246 struct gpio_event_matrix_info *mi = kp->keypad_info;
247 unsigned gpio_keypad_flags = mi->flags;
248
249 if (!kp->use_irq) {
250 /* ignore interrupt while registering the handler */
251 kp->disabled_irq = 1;
252 disable_irq_nosync(irq_in);
253 return IRQ_HANDLED;
254 }
255
256 for (i = 0; i < mi->ninputs; i++)
257 disable_irq_nosync(gpio_to_irq(mi->input_gpios[i]));
258 for (i = 0; i < mi->noutputs; i++) {
259 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
260 gpio_set_value(mi->output_gpios[i],
261 !(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH));
262 else
263 gpio_direction_input(mi->output_gpios[i]);
264 }
265 wake_lock(&kp->wake_lock);
266 hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
267 return IRQ_HANDLED;
268}
269
270static int gpio_keypad_request_irqs(struct gpio_kp *kp)
271{
272 int i;
273 int err;
274 unsigned int irq;
275 unsigned long request_flags;
276 struct gpio_event_matrix_info *mi = kp->keypad_info;
277
278 switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
279 default:
280 request_flags = IRQF_TRIGGER_FALLING;
281 break;
282 case GPIOKPF_ACTIVE_HIGH:
283 request_flags = IRQF_TRIGGER_RISING;
284 break;
285 case GPIOKPF_LEVEL_TRIGGERED_IRQ:
286 request_flags = IRQF_TRIGGER_LOW;
287 break;
288 case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
289 request_flags = IRQF_TRIGGER_HIGH;
290 break;
291 }
292
293 for (i = 0; i < mi->ninputs; i++) {
294 err = irq = gpio_to_irq(mi->input_gpios[i]);
295 if (err < 0)
296 goto err_gpio_get_irq_num_failed;
297 err = request_irq(irq, gpio_keypad_irq_handler, request_flags,
298 "gpio_kp", kp);
299 if (err) {
300 pr_err("gpiomatrix: request_irq failed for input %d, "
301 "irq %d\n", mi->input_gpios[i], irq);
302 goto err_request_irq_failed;
303 }
304 err = enable_irq_wake(irq);
305 if (err) {
306 pr_err("gpiomatrix: set_irq_wake failed for input %d, "
307 "irq %d\n", mi->input_gpios[i], irq);
308 }
309 disable_irq(irq);
310 if (kp->disabled_irq) {
311 kp->disabled_irq = 0;
312 enable_irq(irq);
313 }
314 }
315 return 0;
316
317 for (i = mi->noutputs - 1; i >= 0; i--) {
318 free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
319err_request_irq_failed:
320err_gpio_get_irq_num_failed:
321 ;
322 }
323 return err;
324}
325
326int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
327 struct gpio_event_info *info, void **data, int func)
328{
329 int i;
330 int err;
331 int key_count;
332 struct gpio_kp *kp;
333 struct gpio_event_matrix_info *mi;
334
335 mi = container_of(info, struct gpio_event_matrix_info, info);
336 if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
337 /* TODO: disable scanning */
338 return 0;
339 }
340
341 if (func == GPIO_EVENT_FUNC_INIT) {
342 if (mi->keymap == NULL ||
343 mi->input_gpios == NULL ||
344 mi->output_gpios == NULL) {
345 err = -ENODEV;
346 pr_err("gpiomatrix: Incomplete pdata\n");
347 goto err_invalid_platform_data;
348 }
349 key_count = mi->ninputs * mi->noutputs;
350
351 *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
352 BITS_TO_LONGS(key_count), GFP_KERNEL);
353 if (kp == NULL) {
354 err = -ENOMEM;
355 pr_err("gpiomatrix: Failed to allocate private data\n");
356 goto err_kp_alloc_failed;
357 }
358 kp->input_devs = input_devs;
359 kp->keypad_info = mi;
360 for (i = 0; i < key_count; i++) {
361 unsigned short keyentry = mi->keymap[i];
362 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
363 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
364 if (dev >= input_devs->count) {
365 pr_err("gpiomatrix: bad device index %d >= "
366 "%d for key code %d\n",
367 dev, input_devs->count, keycode);
368 err = -EINVAL;
369 goto err_bad_keymap;
370 }
371 if (keycode && keycode <= KEY_MAX)
372 input_set_capability(input_devs->dev[dev],
373 EV_KEY, keycode);
374 }
375
376 for (i = 0; i < mi->noutputs; i++) {
377 err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
378 if (err) {
379 pr_err("gpiomatrix: gpio_request failed for "
380 "output %d\n", mi->output_gpios[i]);
381 goto err_request_output_gpio_failed;
382 }
383 if (gpio_cansleep(mi->output_gpios[i])) {
384 pr_err("gpiomatrix: unsupported output gpio %d,"
385 " can sleep\n", mi->output_gpios[i]);
386 err = -EINVAL;
387 goto err_output_gpio_configure_failed;
388 }
389 if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
390 err = gpio_direction_output(mi->output_gpios[i],
391 !(mi->flags & GPIOKPF_ACTIVE_HIGH));
392 else
393 err = gpio_direction_input(mi->output_gpios[i]);
394 if (err) {
395 pr_err("gpiomatrix: gpio_configure failed for "
396 "output %d\n", mi->output_gpios[i]);
397 goto err_output_gpio_configure_failed;
398 }
399 }
400 for (i = 0; i < mi->ninputs; i++) {
401 err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
402 if (err) {
403 pr_err("gpiomatrix: gpio_request failed for "
404 "input %d\n", mi->input_gpios[i]);
405 goto err_request_input_gpio_failed;
406 }
407 err = gpio_direction_input(mi->input_gpios[i]);
408 if (err) {
409 pr_err("gpiomatrix: gpio_direction_input failed"
410 " for input %d\n", mi->input_gpios[i]);
411 goto err_gpio_direction_input_failed;
412 }
413 }
414 kp->current_output = mi->noutputs;
415 kp->key_state_changed = 1;
416
417 hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
418 kp->timer.function = gpio_keypad_timer_func;
419 wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
420 err = gpio_keypad_request_irqs(kp);
421 kp->use_irq = err == 0;
422
423 pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
424 "%s%s in %s mode\n", input_devs->dev[0]->name,
425 (input_devs->count > 1) ? "..." : "",
426 kp->use_irq ? "interrupt" : "polling");
427
428 if (kp->use_irq)
429 wake_lock(&kp->wake_lock);
430 hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
431
432 return 0;
433 }
434
435 err = 0;
436 kp = *data;
437
438 if (kp->use_irq)
439 for (i = mi->noutputs - 1; i >= 0; i--)
440 free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
441
442 hrtimer_cancel(&kp->timer);
443 wake_lock_destroy(&kp->wake_lock);
444 for (i = mi->noutputs - 1; i >= 0; i--) {
445err_gpio_direction_input_failed:
446 gpio_free(mi->input_gpios[i]);
447err_request_input_gpio_failed:
448 ;
449 }
450 for (i = mi->noutputs - 1; i >= 0; i--) {
451err_output_gpio_configure_failed:
452 gpio_free(mi->output_gpios[i]);
453err_request_output_gpio_failed:
454 ;
455 }
456err_bad_keymap:
457 kfree(kp);
458err_kp_alloc_failed:
459err_invalid_platform_data:
460 return err;
461}