1811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg/* drivers/input/misc/gpio_matrix.c
2811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg *
3811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * Copyright (C) 2007 Google, Inc.
4811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg *
5811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * This software is licensed under the terms of the GNU General Public
6811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * License version 2, as published by the Free Software Foundation, and
7811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * may be copied, distributed, and modified under those terms.
8811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg *
9811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * This program is distributed in the hope that it will be useful,
10811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * but WITHOUT ANY WARRANTY; without even the implied warranty of
11811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg * GNU General Public License for more details.
13811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg *
14811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg */
15811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
16811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/kernel.h>
17811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/gpio.h>
18811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/gpio_event.h>
19811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/hrtimer.h>
20811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/interrupt.h>
21811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/slab.h>
22811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg#include <linux/wakelock.h>
23811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
24811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstruct gpio_kp {
25811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_input_devs *input_devs;
26811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *keypad_info;
27811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct hrtimer timer;
28811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct wake_lock wake_lock;
29811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int current_output;
30811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int use_irq:1;
31811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int key_state_changed:1;
32811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int last_key_state_changed:1;
33811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int some_keys_pressed:2;
34811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int disabled_irq:1;
35811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned long keys_pressed[0];
36811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg};
37811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
38811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic void clear_phantom_key(struct gpio_kp *kp, int out, int in)
39811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
40811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi = kp->keypad_info;
41811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int key_index = out * mi->ninputs + in;
42811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short keyentry = mi->keymap[key_index];
43811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short keycode = keyentry & MATRIX_KEY_MASK;
44811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short dev = keyentry >> MATRIX_CODE_BITS;
45811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
46811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (!test_bit(keycode, kp->input_devs->dev[dev]->key)) {
47811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
48811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
49811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				"cleared\n", keycode, out, in,
50811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				mi->output_gpios[out], mi->input_gpios[in]);
51811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		__clear_bit(key_index, kp->keys_pressed);
52811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	} else {
53811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (mi->flags & GPIOKPF_PRINT_PHANTOM_KEYS)
54811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_info("gpiomatrix: phantom key %x, %d-%d (%d-%d) "
55811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				"not cleared\n", keycode, out, in,
56811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				mi->output_gpios[out], mi->input_gpios[in]);
57811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
58811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
59811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
60811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic int restore_keys_for_input(struct gpio_kp *kp, int out, int in)
61811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
62811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int rv = 0;
63811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int key_index;
64811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
65811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	key_index = out * kp->keypad_info->ninputs + in;
66811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	while (out < kp->keypad_info->noutputs) {
67811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (test_bit(key_index, kp->keys_pressed)) {
68811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			rv = 1;
69811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			clear_phantom_key(kp, out, in);
70811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
71811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		key_index += kp->keypad_info->ninputs;
72811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		out++;
73811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
74811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return rv;
75811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
76811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
77811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic void remove_phantom_keys(struct gpio_kp *kp)
78811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
79811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int out, in, inp;
80811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int key_index;
81811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
82811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (kp->some_keys_pressed < 3)
83811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return;
84811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
85811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (out = 0; out < kp->keypad_info->noutputs; out++) {
86811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		inp = -1;
87811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		key_index = out * kp->keypad_info->ninputs;
88811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (in = 0; in < kp->keypad_info->ninputs; in++, key_index++) {
89811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (test_bit(key_index, kp->keys_pressed)) {
90811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				if (inp == -1) {
91811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					inp = in;
92811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					continue;
93811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				}
94811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				if (inp >= 0) {
95811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					if (!restore_keys_for_input(kp, out + 1,
96811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg									inp))
97811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg						break;
98811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					clear_phantom_key(kp, out, inp);
99811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					inp = -2;
100811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				}
101811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				restore_keys_for_input(kp, out, in);
102811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
103811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
104811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
105811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
106811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
107811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic void report_key(struct gpio_kp *kp, int key_index, int out, int in)
108811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
109811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi = kp->keypad_info;
110811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int pressed = test_bit(key_index, kp->keys_pressed);
111811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short keyentry = mi->keymap[key_index];
112811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short keycode = keyentry & MATRIX_KEY_MASK;
113811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned short dev = keyentry >> MATRIX_CODE_BITS;
114811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
115811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (pressed != test_bit(keycode, kp->input_devs->dev[dev]->key)) {
116811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (keycode == KEY_RESERVED) {
117811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (mi->flags & GPIOKPF_PRINT_UNMAPPED_KEYS)
118811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_info("gpiomatrix: unmapped key, %d-%d "
119811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"(%d-%d) changed to %d\n",
120811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					out, in, mi->output_gpios[out],
121811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					mi->input_gpios[in], pressed);
122811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		} else {
123811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (mi->flags & GPIOKPF_PRINT_MAPPED_KEYS)
124811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_info("gpiomatrix: key %x, %d-%d (%d-%d) "
125811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"changed to %d\n", keycode,
126811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					out, in, mi->output_gpios[out],
127811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					mi->input_gpios[in], pressed);
128811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			input_report_key(kp->input_devs->dev[dev], keycode, pressed);
129811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
130811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
131811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
132811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
133811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic void report_sync(struct gpio_kp *kp)
134811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
135811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int i;
136811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
137811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = 0; i < kp->input_devs->count; i++)
138811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		input_sync(kp->input_devs->dev[i]);
139811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
140811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
141811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic enum hrtimer_restart gpio_keypad_timer_func(struct hrtimer *timer)
142811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
143811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int out, in;
144811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int key_index;
145811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int gpio;
146811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_kp *kp = container_of(timer, struct gpio_kp, timer);
147811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi = kp->keypad_info;
148811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned gpio_keypad_flags = mi->flags;
149811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned polarity = !!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH);
150811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
151811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	out = kp->current_output;
152811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (out == mi->noutputs) {
153811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		out = 0;
154811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->last_key_state_changed = kp->key_state_changed;
155811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->key_state_changed = 0;
156811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->some_keys_pressed = 0;
157811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	} else {
158811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		key_index = out * mi->ninputs;
159811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (in = 0; in < mi->ninputs; in++, key_index++) {
160811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio = mi->input_gpios[in];
161811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (gpio_get_value(gpio) ^ !polarity) {
162811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				if (kp->some_keys_pressed < 3)
163811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					kp->some_keys_pressed++;
164811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				kp->key_state_changed |= !__test_and_set_bit(
165811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg						key_index, kp->keys_pressed);
166811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			} else
167811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				kp->key_state_changed |= __test_and_clear_bit(
168811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg						key_index, kp->keys_pressed);
169811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
170811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		gpio = mi->output_gpios[out];
171811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
172811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_set_value(gpio, !polarity);
173811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		else
174811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_direction_input(gpio);
175811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		out++;
176811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
177811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	kp->current_output = out;
178811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (out < mi->noutputs) {
179811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		gpio = mi->output_gpios[out];
180811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
181811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_set_value(gpio, polarity);
182811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		else
183811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_direction_output(gpio, polarity);
184811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		hrtimer_start(timer, mi->settle_time, HRTIMER_MODE_REL);
185811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return HRTIMER_NORESTART;
186811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
187811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (gpio_keypad_flags & GPIOKPF_DEBOUNCE) {
188811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (kp->key_state_changed) {
189811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			hrtimer_start(&kp->timer, mi->debounce_delay,
190811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				      HRTIMER_MODE_REL);
191811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			return HRTIMER_NORESTART;
192811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
193811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->key_state_changed = kp->last_key_state_changed;
194811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
195811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (kp->key_state_changed) {
196811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (gpio_keypad_flags & GPIOKPF_REMOVE_SOME_PHANTOM_KEYS)
197811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			remove_phantom_keys(kp);
198811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		key_index = 0;
199811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (out = 0; out < mi->noutputs; out++)
200811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			for (in = 0; in < mi->ninputs; in++, key_index++)
201811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				report_key(kp, key_index, out, in);
202811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		report_sync(kp);
203811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
204811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (!kp->use_irq || kp->some_keys_pressed) {
205811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		hrtimer_start(timer, mi->poll_time, HRTIMER_MODE_REL);
206811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return HRTIMER_NORESTART;
207811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
208811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
209811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	/* No keys are pressed, reenable interrupt */
210811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (out = 0; out < mi->noutputs; out++) {
211811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
212811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_set_value(mi->output_gpios[out], polarity);
213811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		else
214811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_direction_output(mi->output_gpios[out], polarity);
215811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
216811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (in = 0; in < mi->ninputs; in++)
217811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		enable_irq(gpio_to_irq(mi->input_gpios[in]));
218811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	wake_unlock(&kp->wake_lock);
219811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return HRTIMER_NORESTART;
220811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
221811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
222811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic irqreturn_t gpio_keypad_irq_handler(int irq_in, void *dev_id)
223811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
224811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int i;
225811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_kp *kp = dev_id;
226811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi = kp->keypad_info;
227811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned gpio_keypad_flags = mi->flags;
228811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
229811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (!kp->use_irq) {
230811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		/* ignore interrupt while registering the handler */
231811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->disabled_irq = 1;
232811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		disable_irq_nosync(irq_in);
233811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return IRQ_HANDLED;
234811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
235811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
236811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = 0; i < mi->ninputs; i++)
237811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		disable_irq_nosync(gpio_to_irq(mi->input_gpios[i]));
238811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = 0; i < mi->noutputs; i++) {
239811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (gpio_keypad_flags & GPIOKPF_DRIVE_INACTIVE)
240811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_set_value(mi->output_gpios[i],
241811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				!(gpio_keypad_flags & GPIOKPF_ACTIVE_HIGH));
242811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		else
243811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			gpio_direction_input(mi->output_gpios[i]);
244811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
245811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	wake_lock(&kp->wake_lock);
246811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
247811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return IRQ_HANDLED;
248811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
249811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
250811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågstatic int gpio_keypad_request_irqs(struct gpio_kp *kp)
251811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
252811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int i;
253811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int err;
254811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned int irq;
255811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	unsigned long request_flags;
256811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi = kp->keypad_info;
257811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
258811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	switch (mi->flags & (GPIOKPF_ACTIVE_HIGH|GPIOKPF_LEVEL_TRIGGERED_IRQ)) {
259811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	default:
260811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		request_flags = IRQF_TRIGGER_FALLING;
261811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		break;
262811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	case GPIOKPF_ACTIVE_HIGH:
263811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		request_flags = IRQF_TRIGGER_RISING;
264811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		break;
265811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	case GPIOKPF_LEVEL_TRIGGERED_IRQ:
266811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		request_flags = IRQF_TRIGGER_LOW;
267811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		break;
268811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	case GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_ACTIVE_HIGH:
269811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		request_flags = IRQF_TRIGGER_HIGH;
270811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		break;
271811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
272811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
273811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = 0; i < mi->ninputs; i++) {
274811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		err = irq = gpio_to_irq(mi->input_gpios[i]);
275811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (err < 0)
276811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			goto err_gpio_get_irq_num_failed;
277811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		err = request_irq(irq, gpio_keypad_irq_handler, request_flags,
278811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				  "gpio_kp", kp);
279811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (err) {
280811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_err("gpiomatrix: request_irq failed for input %d, "
281811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				"irq %d\n", mi->input_gpios[i], irq);
282811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			goto err_request_irq_failed;
283811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
284811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		err = enable_irq_wake(irq);
285811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (err) {
286811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_err("gpiomatrix: set_irq_wake failed for input %d, "
287811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				"irq %d\n", mi->input_gpios[i], irq);
288811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
289811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		disable_irq(irq);
290811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (kp->disabled_irq) {
291811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			kp->disabled_irq = 0;
292811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			enable_irq(irq);
293811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
294811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
295811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return 0;
296811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
297811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = mi->noutputs - 1; i >= 0; i--) {
298811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
299811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_request_irq_failed:
300811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_gpio_get_irq_num_failed:
301811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		;
302811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
303811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return err;
304811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
305811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
306811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågint gpio_event_matrix_func(struct gpio_event_input_devs *input_devs,
307811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_info *info, void **data, int func)
308811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg{
309811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int i;
310811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int err;
311811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	int key_count;
312811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_kp *kp;
313811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	struct gpio_event_matrix_info *mi;
314811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
315811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	mi = container_of(info, struct gpio_event_matrix_info, info);
316811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (func == GPIO_EVENT_FUNC_SUSPEND || func == GPIO_EVENT_FUNC_RESUME) {
317811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		/* TODO: disable scanning */
318811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return 0;
319811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
320811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
321811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (func == GPIO_EVENT_FUNC_INIT) {
322811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (mi->keymap == NULL ||
323811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		   mi->input_gpios == NULL ||
324811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		   mi->output_gpios == NULL) {
325811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			err = -ENODEV;
326811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_err("gpiomatrix: Incomplete pdata\n");
327811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			goto err_invalid_platform_data;
328811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
329811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		key_count = mi->ninputs * mi->noutputs;
330811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
331811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		*data = kp = kzalloc(sizeof(*kp) + sizeof(kp->keys_pressed[0]) *
332811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				     BITS_TO_LONGS(key_count), GFP_KERNEL);
333811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (kp == NULL) {
334811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			err = -ENOMEM;
335811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			pr_err("gpiomatrix: Failed to allocate private data\n");
336811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			goto err_kp_alloc_failed;
337811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
338811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->input_devs = input_devs;
339811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->keypad_info = mi;
340811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (i = 0; i < key_count; i++) {
341811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			unsigned short keyentry = mi->keymap[i];
342811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			unsigned short keycode = keyentry & MATRIX_KEY_MASK;
343811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			unsigned short dev = keyentry >> MATRIX_CODE_BITS;
344811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (dev >= input_devs->count) {
345811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: bad device index %d >= "
346811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"%d for key code %d\n",
347811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					dev, input_devs->count, keycode);
348811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				err = -EINVAL;
349811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_bad_keymap;
350811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
351811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (keycode && keycode <= KEY_MAX)
352811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				input_set_capability(input_devs->dev[dev],
353811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg							EV_KEY, keycode);
354811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
355811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
356811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (i = 0; i < mi->noutputs; i++) {
357811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			err = gpio_request(mi->output_gpios[i], "gpio_kp_out");
358811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (err) {
359811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: gpio_request failed for "
360811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"output %d\n", mi->output_gpios[i]);
361811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_request_output_gpio_failed;
362811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
363811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (gpio_cansleep(mi->output_gpios[i])) {
364811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: unsupported output gpio %d,"
365811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					" can sleep\n", mi->output_gpios[i]);
366811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				err = -EINVAL;
367811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_output_gpio_configure_failed;
368811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
369811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (mi->flags & GPIOKPF_DRIVE_INACTIVE)
370811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				err = gpio_direction_output(mi->output_gpios[i],
371811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					!(mi->flags & GPIOKPF_ACTIVE_HIGH));
372811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			else
373811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				err = gpio_direction_input(mi->output_gpios[i]);
374811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (err) {
375811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: gpio_configure failed for "
376811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"output %d\n", mi->output_gpios[i]);
377811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_output_gpio_configure_failed;
378811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
379811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
380811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (i = 0; i < mi->ninputs; i++) {
381811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			err = gpio_request(mi->input_gpios[i], "gpio_kp_in");
382811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (err) {
383811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: gpio_request failed for "
384811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					"input %d\n", mi->input_gpios[i]);
385811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_request_input_gpio_failed;
386811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
387811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			err = gpio_direction_input(mi->input_gpios[i]);
388811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			if (err) {
389811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				pr_err("gpiomatrix: gpio_direction_input failed"
390811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg					" for input %d\n", mi->input_gpios[i]);
391811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg				goto err_gpio_direction_input_failed;
392811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			}
393811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		}
394811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->current_output = mi->noutputs;
395811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->key_state_changed = 1;
396811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
397811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
398811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->timer.function = gpio_keypad_timer_func;
399811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		wake_lock_init(&kp->wake_lock, WAKE_LOCK_SUSPEND, "gpio_kp");
400811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		err = gpio_keypad_request_irqs(kp);
401811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		kp->use_irq = err == 0;
402811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
403811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		pr_info("GPIO Matrix Keypad Driver: Start keypad matrix for "
404811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			"%s%s in %s mode\n", input_devs->dev[0]->name,
405811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			(input_devs->count > 1) ? "..." : "",
406811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			kp->use_irq ? "interrupt" : "polling");
407811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
408811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		if (kp->use_irq)
409811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			wake_lock(&kp->wake_lock);
410811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		hrtimer_start(&kp->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
411811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
412811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		return 0;
413811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
414811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
415811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	err = 0;
416811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	kp = *data;
417811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
418811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	if (kp->use_irq)
419811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		for (i = mi->noutputs - 1; i >= 0; i--)
420811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg			free_irq(gpio_to_irq(mi->input_gpios[i]), kp);
421811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg
422811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	hrtimer_cancel(&kp->timer);
423811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	wake_lock_destroy(&kp->wake_lock);
424811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = mi->noutputs - 1; i >= 0; i--) {
425811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_gpio_direction_input_failed:
426811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		gpio_free(mi->input_gpios[i]);
427811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_request_input_gpio_failed:
428811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		;
429811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
430811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	for (i = mi->noutputs - 1; i >= 0; i--) {
431811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_output_gpio_configure_failed:
432811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		gpio_free(mi->output_gpios[i]);
433811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_request_output_gpio_failed:
434811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg		;
435811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	}
436811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_bad_keymap:
437811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	kfree(kp);
438811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_kp_alloc_failed:
439811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevågerr_invalid_platform_data:
440811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg	return err;
441811868bc53546a6046d847c863739fbd6b39514bArve Hjønnevåg}
442