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