aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-yocto-dev/h3600/0003-input-driver-for-microcontroller-keys-on-the-iPaq-h3.patch
blob: cb080e8d1eddbf955e82f1b1fe491040136b456a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
From 96394b690b27fd3b4175b290a179e5e4e9138085 Mon Sep 17 00:00:00 2001
From: Dmitry Artamonow <mad_soft@inbox.ru>
Date: Sat, 21 Mar 2009 16:22:16 +0300
Subject: [PATCH 3/7] input: driver for microcontroller keys on the iPaq h3xxx

This adds a key input driver for the keys found on the h3xxx
iPAQ series.

Based on a driver from handhelds.org 2.6.21 kernel, written
by Alessandro GARDICH.

Signed-off-by: Alessandro GARDICH <gremlin@gremlin.it>
Signed-off-by: Dmitry Artamonow <mad_soft@inbox.ru>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/input/keyboard/Kconfig           |   7 ++
 drivers/input/keyboard/Makefile          |   1 +
 drivers/input/keyboard/ipaq-micro-keys.c | 148 +++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+)
 create mode 100644 drivers/input/keyboard/ipaq-micro-keys.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a673c9f3a0b9..8d4892dfa6e2 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -554,6 +554,13 @@ config KEYBOARD_DAVINCI
 	  To compile this driver as a module, choose M here: the
 	  module will be called davinci_keyscan.
 
+config KEYBOARD_IPAQ_MICRO
+	tristate "Buttons on Micro SoC (iPaq h3100,h3600,h3700)"
+	depends on MFD_IPAQ_MICRO
+	help
+	  This enables support for the buttons attached to
+	  Micro peripheral controller on iPAQ h3100/h3600/h3700
+
 config KEYBOARD_OMAP
 	tristate "TI OMAP keypad support"
 	depends on ARCH_OMAP1
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index a699b6172303..e776af737804 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_KEYBOARD_TCA6416)		+= tca6416-keypad.o
 obj-$(CONFIG_KEYBOARD_TCA8418)		+= tca8418_keypad.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
+obj-$(CONFIG_KEYBOARD_IPAQ_MICRO)	+= ipaq-micro-keys.o
 obj-$(CONFIG_KEYBOARD_IMX)		+= imx_keypad.o
 obj-$(CONFIG_KEYBOARD_HP6XX)		+= jornada680_kbd.o
 obj-$(CONFIG_KEYBOARD_HP7XX)		+= jornada720_kbd.o
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
new file mode 100644
index 000000000000..7ca8b738cc73
--- /dev/null
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -0,0 +1,148 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * h3600 atmel micro companion support, key subdevice
+ * based on previous kernel 2.4 version
+ * Author : Alessandro Gardich <gremlin@gremlin.it>
+ * Author : Linus Walleij <linus.walleij@linaro.org>
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ipaq-micro.h>
+
+struct ipaq_micro_keys {
+	struct ipaq_micro *micro;
+	struct input_dev *input;
+};
+
+static int keycodes[] = {
+	KEY_RECORD,		/* 1:  Record button			*/
+	KEY_CALENDAR,		/* 2:  Calendar				*/
+	KEY_ADDRESSBOOK,	/* 3:  Contacts (looks like Outlook)	*/
+	KEY_MAIL,		/* 4:  Envelope (Q on older iPAQs)	*/
+	KEY_HOMEPAGE,		/* 5:  Start (looks like swoopy arrow)	*/
+	KEY_UP,			/* 6:  Up				*/
+	KEY_RIGHT,		/* 7:  Right				*/
+	KEY_LEFT,		/* 8:  Left				*/
+	KEY_DOWN,		/* 9:  Down				*/
+};
+
+static void micro_key_receive(void *data, int len, unsigned char *msg)
+{
+	struct ipaq_micro_keys *keys = data;
+	int key, down;
+
+	down = (0x80 & msg[0]) ? 1 : 0;
+	key  = 0x7f & msg[0];
+
+	if (key < ARRAY_SIZE(keycodes)) {
+		input_report_key(keys->input, keycodes[key], down);
+		input_sync(keys->input);
+	}
+}
+
+static int micro_key_probe(struct platform_device *pdev)
+{
+	struct ipaq_micro_keys *keys;
+	int ret;
+	int i;
+
+	keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
+	if (!keys)
+		return -ENOMEM;
+	keys->input = input_allocate_device();
+	if (!keys->input)
+		return -ENOMEM;
+	keys->micro = dev_get_drvdata(pdev->dev.parent);
+	keys->input->evbit[0] = BIT(EV_KEY);
+	set_bit(EV_KEY, keys->input->evbit);
+	for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+		set_bit(keycodes[i], keys->input->keybit);
+
+	keys->input->name = "h3600 micro keys";
+
+	ret = input_register_device(keys->input);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, keys);
+	spin_lock(&keys->micro->lock);
+	keys->micro->key = micro_key_receive;
+	keys->micro->key_data = keys;
+	spin_unlock(&keys->micro->lock);
+
+	return 0;
+}
+
+static int micro_key_remove(struct platform_device *pdev)
+{
+	struct ipaq_micro_keys *keys = platform_get_drvdata(pdev);
+
+	input_unregister_device(keys->input);
+
+	spin_lock(&keys->micro->lock);
+	keys->micro->key = NULL;
+	keys->micro->key_data = NULL;
+	spin_unlock(&keys->micro->lock);
+
+	return 0;
+}
+
+static int micro_key_suspend(struct device *dev)
+{
+	struct ipaq_micro_keys *keys = dev_get_drvdata(dev);
+
+	spin_lock(&keys->micro->lock);
+	keys->micro->key = NULL;
+	keys->micro->key_data = NULL;
+	spin_unlock(&keys->micro->lock);
+
+	return 0;
+}
+
+static int micro_key_resume(struct device *dev)
+{
+	struct ipaq_micro_keys *keys = dev_get_drvdata(dev);
+
+	spin_lock(&keys->micro->lock);
+	keys->micro->key = micro_key_receive;
+	keys->micro->key_data = keys;
+	spin_unlock(&keys->micro->lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops micro_key_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(micro_key_suspend, micro_key_resume)
+};
+
+struct platform_driver micro_key_device_driver = {
+	.driver = {
+		.name    = "ipaq-micro-keys",
+		.pm	= &micro_key_dev_pm_ops,
+	},
+	.probe   = micro_key_probe,
+	.remove  = micro_key_remove,
+};
+module_platform_driver(micro_key_device_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("driver for iPAQ Atmel micro keys");
+MODULE_ALIAS("platform:ipaq-micro-keys");
-- 
1.9.0