]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/dream/gpio_matrix.c
Merge branch 'preempt' into release
[mv-sheeva.git] / drivers / staging / dream / gpio_matrix.c
1 /* 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
23 struct 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
36 static 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
56 static 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
73 static 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
103 static 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
126 static 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
206 static 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
230 static 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);
275 err_request_irq_failed:
276 err_gpio_get_irq_num_failed:
277                 ;
278         }
279         return err;
280 }
281
282 int 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--) {
391 err_gpio_direction_input_failed:
392                 gpio_free(mi->input_gpios[i]);
393 err_request_input_gpio_failed:
394                 ;
395         }
396         for (i = mi->noutputs - 1; i >= 0; i--) {
397 err_output_gpio_configure_failed:
398                 gpio_free(mi->output_gpios[i]);
399 err_request_output_gpio_failed:
400                 ;
401         }
402         kfree(kp);
403 err_kp_alloc_failed:
404 err_invalid_platform_data:
405         return err;
406 }