• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/dream/
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
23struct 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
35static 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
55static 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
72static 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
102static 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
125static 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
204static 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
227static 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);
272err_request_irq_failed:
273err_gpio_get_irq_num_failed:
274		;
275	}
276	return err;
277}
278
279int 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--) {
384err_gpio_direction_input_failed:
385		gpio_free(mi->input_gpios[i]);
386err_request_input_gpio_failed:
387		;
388	}
389	for (i = mi->noutputs - 1; i >= 0; i--) {
390err_output_gpio_configure_failed:
391		gpio_free(mi->output_gpios[i]);
392err_request_output_gpio_failed:
393		;
394	}
395	kfree(kp);
396err_kp_alloc_failed:
397err_invalid_platform_data:
398	return err;
399}
400