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