blob: f645471b54dd5a8abbf009622a5492c3e98500a7 [file] [log] [blame]
Arve Hjønnevåg72fc6242008-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>
23
24struct gpio_kp {
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -070025 struct gpio_event_input_devs *input_devs;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070026 struct gpio_event_matrix_info *keypad_info;
27 struct hrtimer timer;
28 struct wake_lock wake_lock;
29 int current_output;
30 unsigned int use_irq:1;
31 unsigned int key_state_changed:1;
32 unsigned int last_key_state_changed:1;
33 unsigned int some_keys_pressed:2;
34 unsigned long keys_pressed[0];
35};
36
37static void clear_phantom_key(struct gpio_kp *kp, int out, int in)
38{
39 struct gpio_event_matrix_info *mi = kp->keypad_info;
40 int key_index = out * mi->ninputs + in;
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -070041 unsigned short keyentry = mi->keymap[key_index];
42 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
43 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070044
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -070045 if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) {
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -070046 if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
47 pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
48 "cleared\n", keycode, out, in,
49 mi->output_gpios[out], mi->input_gpios[in]);
50 __clear_bit(key_index, kp->keys_pressed);
51 } else {
52 if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
53 pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
54 "not cleared\n", keycode, out, in,
55 mi->output_gpios[out], mi->input_gpios[in]);
56 }
57}
58
59static int restore_keys_for_input(struct gpio_kp *kp, int out, int in)
60{
61 int rv = 0;
62 int key_index;
63
64 key_index = out * kp->keypad_info->ninputs + in;
65 while (out < kp->keypad_info->noutputs) {
66 if (test_bit(key_index, kp->keys_pressed)) {
67 rv = 1;
68 clear_phantom_key(kp, out, in);
69 }
70 key_index += kp->keypad_info->ninputs;
71 out++;
72 }
73 return rv;
74}
75
76static void remove_phantom_keys(struct gpio_kp *kp)
77{
78 int out, in, inp;
79 int key_index;
80
81 if (kp->some_keys_pressed < 3)
82 return;
83
84 for (out = 0; out < kp->keypad_info->noutputs; out++) {
85 inp = -1;
86 key_index = out * kp->keypad_info->ninputs;
87 for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) {
88 if (test_bit(key_index, kp->keys_pressed)) {
89 if (inp == -1) {
90 inp = in;
91 continue;
92 }
93 if (inp >= 0) {
94 if (!restore_keys_for_input(kp, out + 1,
95 inp))
96 break;
97 clear_phantom_key(kp, out, inp);
98 inp = -2;
99 }
100 restore_keys_for_input(kp, out, in);
101 }
102 }
103 }
104}
105
106static void report_key(struct gpio_kp *kp, int key_index, int out, int in)
107{
108 struct gpio_event_matrix_info *mi = kp->keypad_info;
109 int pressed = test_bit(key_index, kp->keys_pressed);
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700110 unsigned short keyentry = mi->keymap[key_index];
111 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
112 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
113
114 if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) {
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700115 if (keycode == KEY_RESERVED) {
116 if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
117 pr_info("gpiomatrix: unmapped key, %d-%d "
118 "(%d-%d) changed to %d\n",
119 out, in, mi->output_gpios[out],
120 mi->input_gpios[in], pressed);
121 } else {
122 if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS)
123 pr_info("gpiomatrix: key %x, %d-%d (%d-%d) "
124 "changed to %d\n", keycode,
125 out, in, mi->output_gpios[out],
126 mi->input_gpios[in], pressed);
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700127 input_report_key(kp->input_devs->dev[dev], keycode, pressed);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700128 }
129 }
130}
131
132static enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
133{
134 int out, in;
135 int key_index;
136 int gpio;
137 struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer);
138 struct gpio_event_matrix_info *mi = kp->keypad_info;
139 unsigned gpio_keypad_flags = mi->flags;
140 unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH);
141
142 out = kp->current_output;
143 if (out == mi->noutputs) {
144 out = 0;
145 kp->last_key_state_changed = kp->key_state_changed;
146 kp->key_state_changed = 0;
147 kp->some_keys_pressed = 0;
148 } else {
149 key_index = out * mi->ninputs;
150 for (in = 0; in < mi->ninputs; in++, key_index++) {
151 gpio = mi->input_gpios[in];
152 if (gpio_get_value(gpio) ^ !polarity) {
153 if (kp->some_keys_pressed < 3)
154 kp->some_keys_pressed++;
155 kp->key_state_changed |= !__test_and_set_bit(
156 key_index, kp->keys_pressed);
157 } else
158 kp->key_state_changed |= __test_and_clear_bit(
159 key_index, kp->keys_pressed);
160 }
161 gpio = mi->output_gpios[out];
162 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
163 gpio_set_value(gpio, !polarity);
164 else
165 gpio_direction_input(gpio);
166 out++;
167 }
168 kp->current_output = out;
169 if (out < mi->noutputs) {
170 gpio = mi->output_gpios[out];
171 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
172 gpio_set_value(gpio, polarity);
173 else
174 gpio_direction_output(gpio, polarity);
175 hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL);
176 return HRTIMER_NORESTART;
177 }
178 if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) {
179 if (kp->key_state_changed) {
180 hrtimer_start(&kp->timer, mi->debounce_delay,
181 HRTIMER_MODE_REL);
182 return HRTIMER_NORESTART;
183 }
184 kp->key_state_changed = kp->last_key_state_changed;
185 }
186 if (kp->key_state_changed) {
187 if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS)
188 remove_phantom_keys(kp);
189 key_index = 0;
190 for (out = 0; out < mi->noutputs; out++)
191 for (in = 0; in < mi->ninputs; in++, key_index++)
192 report_key(kp, key_index, out, in);
193 }
194 if (!kp->use_irq || kp->some_keys_pressed) {
195 hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL);
196 return HRTIMER_NORESTART;
197 }
198
199 /* No keys are pressed, reenable interrupt */
200 for (out = 0; out < mi->noutputs; out++) {
201 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
202 gpio_set_value(mi->output_gpios[out], polarity);
203 else
204 gpio_direction_output(mi->output_gpios[out], polarity);
205 }
206 for (in = 0; in < mi->ninputs; in++)
207 enable_irq(gpio_to_irq(mi->input_gpios[in]));
208 wake_unlock(&kp->wake_lock);
209 return HRTIMER_NORESTART;
210}
211
212static irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
213{
214 int i;
215 struct gpio_kp *kp = dev_id;
216 struct gpio_event_matrix_info *mi = kp->keypad_info;
217 unsigned gpio_keypad_flags = mi->flags;
218
219 if (!kp->use_irq) /* ignore interrupt while registering the handler */
220 return IRQ_HANDLED;
221
222 for (i = 0; i < mi->ninputs; i++)
Arve Hjønnevåg9be7b632009-04-17 18:24:59 -0700223 disable_irq_nosync(gpio_to_irq(mi->input_gpios[i]));
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700224 for (i = 0; i < mi->noutputs; i++) {
225 if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
226 gpio_set_value(mi->output_gpios[i],
227 !(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH));
228 else
229 gpio_direction_input(mi->output_gpios[i]);
230 }
231 wake_lock(&kp->wake_lock);
232 hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
233 return IRQ_HANDLED;
234}
235
236static int gpio_keypad_request_irqs(struct gpio_kp *kp)
237{
238 int i;
239 int err;
240 unsigned int irq;
241 unsigned long request_flags;
242 struct gpio_event_matrix_info *mi = kp->keypad_info;
243
244 switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
245 default:
246 request_flags = IRQF_TRIGGER_FALLING;
247 break;
248 case GPIOKPF_ACTIVE_HIGH:
249 request_flags = IRQF_TRIGGER_RISING;
250 break;
251 case GPIOKPF_LEVEL_TRIGGERED_IRQ:
252 request_flags = IRQF_TRIGGER_LOW;
253 break;
254 case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
255 request_flags = IRQF_TRIGGER_HIGH;
256 break;
257 }
258
259 for (i = 0; i < mi->ninputs; i++) {
260 err = irq = gpio_to_irq(mi->input_gpios[i]);
261 if (err < 0)
262 goto err_gpio_get_irq_num_failed;
263 err = request_irq(irq, gpio_keypad_irq_handler, request_flags,
264 "gpio_kp", kp);
265 if (err) {
266 pr_err("gpiomatrix: request_irq failed for input %d, "
267 "irq %d\n", mi->input_gpios[i], irq);
268 goto err_request_irq_failed;
269 }
270 err = set_irq_wake(irq, 1);
271 if (err) {
272 pr_err("gpiomatrix: set_irq_wake failed for input %d, "
273 "irq %d\n", mi->input_gpios[i], irq);
274 }
275 disable_irq(irq);
276 }
277 return 0;
278
279 for (i = mi->noutputs - 1; i >= 0; i--) {
280 free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
281err_request_irq_failed:
282err_gpio_get_irq_num_failed:
283 ;
284 }
285 return err;
286}
287
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700288int gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700289 struct gpio_event_info *info, void **data, int func)
290{
291 int i;
292 int err;
293 int key_count;
294 struct gpio_kp *kp;
295 struct gpio_event_matrix_info *mi;
296
297 mi = container_of(info, struct gpio_event_matrix_info, info);
298 if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
299 /* TODO: disable scanning */
300 return 0;
301 }
302
303 if (func == GPIO_EVENT_FUNC_INIT) {
304 if (mi->keymap == NULL ||
305 mi->input_gpios == NULL ||
306 mi->output_gpios == NULL) {
307 err = -ENODEV;
308 pr_err("gpiomatrix: Incomplete pdata\n");
309 goto err_invalid_platform_data;
310 }
311 key_count = mi->ninputs * mi->noutputs;
312
313 *data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
314 BITS_TO_LONGS(key_count), GFP_KERNEL);
315 if (kp == NULL) {
316 err = -ENOMEM;
317 pr_err("gpiomatrix: Failed to allocate private data\n");
318 goto err_kp_alloc_failed;
319 }
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700320 kp->input_devs = input_devs;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700321 kp->keypad_info = mi;
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700322 for (i = 0; i < key_count; i++) {
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700323 unsigned short keyentry = mi->keymap[i];
324 unsigned short keycode = keyentry & MATRIX_KEY_MASK;
325 unsigned short dev = keyentry >> MATRIX_CODE_BITS;
326 if (dev >= input_devs->count) {
327 pr_err("gpiomatrix: bad device index %d >= "
328 "%d for key code %d\n",
329 dev, input_devs->count, keycode);
330 err = -EINVAL;
331 goto err_bad_keymap;
332 }
333 if (keycode && keycode <= KEY_MAX)
334 input_set_capability(input_devs->dev[dev],
335 EV_KEY, keycode);
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700336 }
337
338 for (i = 0; i < mi->noutputs; i++) {
339 if (gpio_cansleep(mi->output_gpios[i])) {
340 pr_err("gpiomatrix: unsupported output gpio %d,"
341 " can sleep\n", mi->output_gpios[i]);
342 err = -EINVAL;
343 goto err_request_output_gpio_failed;
344 }
345 err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
346 if (err) {
347 pr_err("gpiomatrix: gpio_request failed for "
348 "output %d\n", mi->output_gpios[i]);
349 goto err_request_output_gpio_failed;
350 }
351 if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
352 err = gpio_direction_output(mi->output_gpios[i],
353 !(mi->flags & GPIOKPF_ACTIVE_HIGH));
354 else
355 err = gpio_direction_input(mi->output_gpios[i]);
356 if (err) {
357 pr_err("gpiomatrix: gpio_configure failed for "
358 "output %d\n", mi->output_gpios[i]);
359 goto err_output_gpio_configure_failed;
360 }
361 }
362 for (i = 0; i < mi->ninputs; i++) {
363 err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
364 if (err) {
365 pr_err("gpiomatrix: gpio_request failed for "
366 "input %d\n", mi->input_gpios[i]);
367 goto err_request_input_gpio_failed;
368 }
369 err = gpio_direction_input(mi->input_gpios[i]);
370 if (err) {
371 pr_err("gpiomatrix: gpio_direction_input failed"
372 " for input %d\n", mi->input_gpios[i]);
373 goto err_gpio_direction_input_failed;
374 }
375 }
376 kp->current_output = mi->noutputs;
377 kp->key_state_changed = 1;
378
379 hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
380 kp->timer.function = gpio_keypad_timer_func;
381 wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
382 err = gpio_keypad_request_irqs(kp);
383 kp->use_irq = err == 0;
384
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700385 pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
386 "%s%s in %s mode\n", input_devs->dev[0]->name,
387 (input_devs->count > 1) ? "..." : "",
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700388 kp->use_irq ? "interrupt" : "polling");
389
390 if (kp->use_irq)
391 wake_lock(&kp->wake_lock);
392 hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
393
394 return 0;
395 }
396
397 err = 0;
398 kp = *data;
399
400 if (kp->use_irq)
401 for (i = mi->noutputs - 1; i >= 0; i--)
402 free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
403
404 hrtimer_cancel(&kp->timer);
405 wake_lock_destroy(&kp->wake_lock);
406 for (i = mi->noutputs - 1; i >= 0; i--) {
407err_gpio_direction_input_failed:
408 gpio_free(mi->input_gpios[i]);
409err_request_input_gpio_failed:
410 ;
411 }
412 for (i = mi->noutputs - 1; i >= 0; i--) {
413err_output_gpio_configure_failed:
414 gpio_free(mi->output_gpios[i]);
415err_request_output_gpio_failed:
416 ;
417 }
Arve Hjønnevåg0da26bf2009-07-24 15:19:56 -0700418err_bad_keymap:
Arve Hjønnevåg72fc6242008-10-15 18:23:47 -0700419 kfree(kp);
420err_kp_alloc_failed:
421err_invalid_platform_data:
422 return err;
423}