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