diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 18:39:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 18:39:36 -0400 |
commit | 0dd52d0df02733dfc2d5f3824e41b96492305384 (patch) | |
tree | 4cfd84b7a66d71d83c624275d889136fb23a33c9 /drivers/input/keyboard | |
parent | c37efa932598de5e30330a1414e34d9e082e0d9e (diff) | |
parent | fde1132374c9ba7da98a73b9a3c150dca6cf8502 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: add driver for Atmel AT42QT2160 Sensor Chip
Input: max7359 - use threaded IRQs
Input: add driver for Maxim MAX7359 key switch controller
Input: add driver for ADP5588 QWERTY I2C Keypad
Input: add touchscreen driver for MELFAS MCS-5000 controller
Input: add driver for OpenCores Keyboard Controller
Input: dm355evm_keys - remove dm355evm_keys_hardirq
Input: synaptics_i2c - switch to using __cancel_delayed_work()
Input: ad7879 - add support for AD7889
Input: atkbd - rely on input core to restore state on resume
Input: add generic suspend and resume for input devices
Input: libps2 - additional locking for i8042 ports
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/Kconfig | 40 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 4 | ||||
-rw-r--r-- | drivers/input/keyboard/adp5588-keys.c | 361 | ||||
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 25 | ||||
-rw-r--r-- | drivers/input/keyboard/max7359_keypad.c | 330 | ||||
-rw-r--r-- | drivers/input/keyboard/opencores-kbd.c | 180 | ||||
-rw-r--r-- | drivers/input/keyboard/qt2160.c | 397 |
7 files changed, 1312 insertions, 25 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 3525c19be428..ee98b1bc5d89 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -24,6 +24,16 @@ config KEYBOARD_AAED2000 | |||
24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
25 | module will be called aaed2000_kbd. | 25 | module will be called aaed2000_kbd. |
26 | 26 | ||
27 | config KEYBOARD_ADP5588 | ||
28 | tristate "ADP5588 I2C QWERTY Keypad and IO Expander" | ||
29 | depends on I2C | ||
30 | help | ||
31 | Say Y here if you want to use a ADP5588 attached to your | ||
32 | system I2C bus. | ||
33 | |||
34 | To compile this driver as a module, choose M here: the | ||
35 | module will be called adp5588-keys. | ||
36 | |||
27 | config KEYBOARD_AMIGA | 37 | config KEYBOARD_AMIGA |
28 | tristate "Amiga keyboard" | 38 | tristate "Amiga keyboard" |
29 | depends on AMIGA | 39 | depends on AMIGA |
@@ -104,6 +114,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES | |||
104 | right-hand column will be interpreted as the key shown in the | 114 | right-hand column will be interpreted as the key shown in the |
105 | left-hand column. | 115 | left-hand column. |
106 | 116 | ||
117 | config QT2160 | ||
118 | tristate "Atmel AT42QT2160 Touch Sensor Chip" | ||
119 | depends on I2C && EXPERIMENTAL | ||
120 | help | ||
121 | If you say yes here you get support for Atmel AT42QT2160 Touch | ||
122 | Sensor chip as a keyboard input. | ||
123 | |||
124 | This driver can also be built as a module. If so, the module | ||
125 | will be called qt2160. | ||
126 | |||
107 | config KEYBOARD_BFIN | 127 | config KEYBOARD_BFIN |
108 | tristate "Blackfin BF54x keypad support" | 128 | tristate "Blackfin BF54x keypad support" |
109 | depends on (BF54x && !BF544) | 129 | depends on (BF54x && !BF544) |
@@ -251,6 +271,17 @@ config KEYBOARD_MAPLE | |||
251 | To compile this driver as a module, choose M here: the | 271 | To compile this driver as a module, choose M here: the |
252 | module will be called maple_keyb. | 272 | module will be called maple_keyb. |
253 | 273 | ||
274 | config KEYBOARD_MAX7359 | ||
275 | tristate "Maxim MAX7359 Key Switch Controller" | ||
276 | depends on I2C | ||
277 | help | ||
278 | If you say yes here you get support for the Maxim MAX7359 Key | ||
279 | Switch Controller chip. This providers microprocessors with | ||
280 | management of up to 64 key switches | ||
281 | |||
282 | To compile this driver as a module, choose M here: the | ||
283 | module will be called max7359_keypad. | ||
284 | |||
254 | config KEYBOARD_NEWTON | 285 | config KEYBOARD_NEWTON |
255 | tristate "Newton keyboard" | 286 | tristate "Newton keyboard" |
256 | select SERIO | 287 | select SERIO |
@@ -260,6 +291,15 @@ config KEYBOARD_NEWTON | |||
260 | To compile this driver as a module, choose M here: the | 291 | To compile this driver as a module, choose M here: the |
261 | module will be called newtonkbd. | 292 | module will be called newtonkbd. |
262 | 293 | ||
294 | config KEYBOARD_OPENCORES | ||
295 | tristate "OpenCores Keyboard Controller" | ||
296 | help | ||
297 | Say Y here if you want to use the OpenCores Keyboard Controller | ||
298 | http://www.opencores.org/project,keyboardcontroller | ||
299 | |||
300 | To compile this driver as a module, choose M here; the | ||
301 | module will be called opencores-kbd. | ||
302 | |||
263 | config KEYBOARD_PXA27x | 303 | config KEYBOARD_PXA27x |
264 | tristate "PXA27x/PXA3xx keypad support" | 304 | tristate "PXA27x/PXA3xx keypad support" |
265 | depends on PXA27x || PXA3xx | 305 | depends on PXA27x || PXA3xx |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 8a7a22b30266..babad5e58b77 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | ||
8 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
9 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 10 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
10 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
@@ -21,10 +22,13 @@ obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | |||
21 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 22 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
22 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | 23 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o |
23 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o | 24 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o |
25 | obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o | ||
24 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 26 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
25 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 27 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
28 | obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o | ||
26 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 29 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
27 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 30 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
31 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | ||
28 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 32 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
29 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 33 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 34 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c new file mode 100644 index 000000000000..d48c808d5928 --- /dev/null +++ b/drivers/input/keyboard/adp5588-keys.c | |||
@@ -0,0 +1,361 @@ | |||
1 | /* | ||
2 | * File: drivers/input/keyboard/adp5588_keys.c | ||
3 | * Description: keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander | ||
4 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
5 | * | ||
6 | * Copyright (C) 2008-2009 Analog Devices Inc. | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/version.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/i2c.h> | ||
21 | |||
22 | #include <linux/i2c/adp5588.h> | ||
23 | |||
24 | /* Configuration Register1 */ | ||
25 | #define AUTO_INC (1 << 7) | ||
26 | #define GPIEM_CFG (1 << 6) | ||
27 | #define OVR_FLOW_M (1 << 5) | ||
28 | #define INT_CFG (1 << 4) | ||
29 | #define OVR_FLOW_IEN (1 << 3) | ||
30 | #define K_LCK_IM (1 << 2) | ||
31 | #define GPI_IEN (1 << 1) | ||
32 | #define KE_IEN (1 << 0) | ||
33 | |||
34 | /* Interrupt Status Register */ | ||
35 | #define CMP2_INT (1 << 5) | ||
36 | #define CMP1_INT (1 << 4) | ||
37 | #define OVR_FLOW_INT (1 << 3) | ||
38 | #define K_LCK_INT (1 << 2) | ||
39 | #define GPI_INT (1 << 1) | ||
40 | #define KE_INT (1 << 0) | ||
41 | |||
42 | /* Key Lock and Event Counter Register */ | ||
43 | #define K_LCK_EN (1 << 6) | ||
44 | #define LCK21 0x30 | ||
45 | #define KEC 0xF | ||
46 | |||
47 | /* Key Event Register xy */ | ||
48 | #define KEY_EV_PRESSED (1 << 7) | ||
49 | #define KEY_EV_MASK (0x7F) | ||
50 | |||
51 | #define KP_SEL(x) (0xFFFF >> (16 - x)) /* 2^x-1 */ | ||
52 | |||
53 | #define KEYP_MAX_EVENT 10 | ||
54 | |||
55 | /* | ||
56 | * Early pre 4.0 Silicon required to delay readout by at least 25ms, | ||
57 | * since the Event Counter Register updated 25ms after the interrupt | ||
58 | * asserted. | ||
59 | */ | ||
60 | #define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4) | ||
61 | |||
62 | struct adp5588_kpad { | ||
63 | struct i2c_client *client; | ||
64 | struct input_dev *input; | ||
65 | struct delayed_work work; | ||
66 | unsigned long delay; | ||
67 | unsigned short keycode[ADP5588_KEYMAPSIZE]; | ||
68 | }; | ||
69 | |||
70 | static int adp5588_read(struct i2c_client *client, u8 reg) | ||
71 | { | ||
72 | int ret = i2c_smbus_read_byte_data(client, reg); | ||
73 | |||
74 | if (ret < 0) | ||
75 | dev_err(&client->dev, "Read Error\n"); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static int adp5588_write(struct i2c_client *client, u8 reg, u8 val) | ||
81 | { | ||
82 | return i2c_smbus_write_byte_data(client, reg, val); | ||
83 | } | ||
84 | |||
85 | static void adp5588_work(struct work_struct *work) | ||
86 | { | ||
87 | struct adp5588_kpad *kpad = container_of(work, | ||
88 | struct adp5588_kpad, work.work); | ||
89 | struct i2c_client *client = kpad->client; | ||
90 | int i, key, status, ev_cnt; | ||
91 | |||
92 | status = adp5588_read(client, INT_STAT); | ||
93 | |||
94 | if (status & OVR_FLOW_INT) /* Unlikely and should never happen */ | ||
95 | dev_err(&client->dev, "Event Overflow Error\n"); | ||
96 | |||
97 | if (status & KE_INT) { | ||
98 | ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC; | ||
99 | if (ev_cnt) { | ||
100 | for (i = 0; i < ev_cnt; i++) { | ||
101 | key = adp5588_read(client, Key_EVENTA + i); | ||
102 | input_report_key(kpad->input, | ||
103 | kpad->keycode[(key & KEY_EV_MASK) - 1], | ||
104 | key & KEY_EV_PRESSED); | ||
105 | } | ||
106 | input_sync(kpad->input); | ||
107 | } | ||
108 | } | ||
109 | adp5588_write(client, INT_STAT, status); /* Status is W1C */ | ||
110 | } | ||
111 | |||
112 | static irqreturn_t adp5588_irq(int irq, void *handle) | ||
113 | { | ||
114 | struct adp5588_kpad *kpad = handle; | ||
115 | |||
116 | /* | ||
117 | * use keventd context to read the event fifo registers | ||
118 | * Schedule readout at least 25ms after notification for | ||
119 | * REVID < 4 | ||
120 | */ | ||
121 | |||
122 | schedule_delayed_work(&kpad->work, kpad->delay); | ||
123 | |||
124 | return IRQ_HANDLED; | ||
125 | } | ||
126 | |||
127 | static int __devinit adp5588_setup(struct i2c_client *client) | ||
128 | { | ||
129 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; | ||
130 | int i, ret; | ||
131 | |||
132 | ret = adp5588_write(client, KP_GPIO1, KP_SEL(pdata->rows)); | ||
133 | ret |= adp5588_write(client, KP_GPIO2, KP_SEL(pdata->cols) & 0xFF); | ||
134 | ret |= adp5588_write(client, KP_GPIO3, KP_SEL(pdata->cols) >> 8); | ||
135 | |||
136 | if (pdata->en_keylock) { | ||
137 | ret |= adp5588_write(client, UNLOCK1, pdata->unlock_key1); | ||
138 | ret |= adp5588_write(client, UNLOCK2, pdata->unlock_key2); | ||
139 | ret |= adp5588_write(client, KEY_LCK_EC_STAT, K_LCK_EN); | ||
140 | } | ||
141 | |||
142 | for (i = 0; i < KEYP_MAX_EVENT; i++) | ||
143 | ret |= adp5588_read(client, Key_EVENTA); | ||
144 | |||
145 | ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT | | ||
146 | OVR_FLOW_INT | K_LCK_INT | | ||
147 | GPI_INT | KE_INT); /* Status is W1C */ | ||
148 | |||
149 | ret |= adp5588_write(client, CFG, INT_CFG | OVR_FLOW_IEN | KE_IEN); | ||
150 | |||
151 | if (ret < 0) { | ||
152 | dev_err(&client->dev, "Write Error\n"); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int __devinit adp5588_probe(struct i2c_client *client, | ||
160 | const struct i2c_device_id *id) | ||
161 | { | ||
162 | struct adp5588_kpad *kpad; | ||
163 | struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; | ||
164 | struct input_dev *input; | ||
165 | unsigned int revid; | ||
166 | int ret, i; | ||
167 | int error; | ||
168 | |||
169 | if (!i2c_check_functionality(client->adapter, | ||
170 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
171 | dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); | ||
172 | return -EIO; | ||
173 | } | ||
174 | |||
175 | if (!pdata) { | ||
176 | dev_err(&client->dev, "no platform data?\n"); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | ||
181 | dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | if (pdata->keymapsize != ADP5588_KEYMAPSIZE) { | ||
186 | dev_err(&client->dev, "invalid keymapsize\n"); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | if (!client->irq) { | ||
191 | dev_err(&client->dev, "no IRQ?\n"); | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | kpad = kzalloc(sizeof(*kpad), GFP_KERNEL); | ||
196 | input = input_allocate_device(); | ||
197 | if (!kpad || !input) { | ||
198 | error = -ENOMEM; | ||
199 | goto err_free_mem; | ||
200 | } | ||
201 | |||
202 | kpad->client = client; | ||
203 | kpad->input = input; | ||
204 | INIT_DELAYED_WORK(&kpad->work, adp5588_work); | ||
205 | |||
206 | ret = adp5588_read(client, DEV_ID); | ||
207 | if (ret < 0) { | ||
208 | error = ret; | ||
209 | goto err_free_mem; | ||
210 | } | ||
211 | |||
212 | revid = (u8) ret & ADP5588_DEVICE_ID_MASK; | ||
213 | if (WA_DELAYED_READOUT_REVID(revid)) | ||
214 | kpad->delay = msecs_to_jiffies(30); | ||
215 | |||
216 | input->name = client->name; | ||
217 | input->phys = "adp5588-keys/input0"; | ||
218 | input->dev.parent = &client->dev; | ||
219 | |||
220 | input_set_drvdata(input, kpad); | ||
221 | |||
222 | input->id.bustype = BUS_I2C; | ||
223 | input->id.vendor = 0x0001; | ||
224 | input->id.product = 0x0001; | ||
225 | input->id.version = revid; | ||
226 | |||
227 | input->keycodesize = sizeof(kpad->keycode[0]); | ||
228 | input->keycodemax = pdata->keymapsize; | ||
229 | input->keycode = kpad->keycode; | ||
230 | |||
231 | memcpy(kpad->keycode, pdata->keymap, | ||
232 | pdata->keymapsize * input->keycodesize); | ||
233 | |||
234 | /* setup input device */ | ||
235 | __set_bit(EV_KEY, input->evbit); | ||
236 | |||
237 | if (pdata->repeat) | ||
238 | __set_bit(EV_REP, input->evbit); | ||
239 | |||
240 | for (i = 0; i < input->keycodemax; i++) | ||
241 | __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); | ||
242 | __clear_bit(KEY_RESERVED, input->keybit); | ||
243 | |||
244 | error = input_register_device(input); | ||
245 | if (error) { | ||
246 | dev_err(&client->dev, "unable to register input device\n"); | ||
247 | goto err_free_mem; | ||
248 | } | ||
249 | |||
250 | error = request_irq(client->irq, adp5588_irq, | ||
251 | IRQF_TRIGGER_FALLING | IRQF_DISABLED, | ||
252 | client->dev.driver->name, kpad); | ||
253 | if (error) { | ||
254 | dev_err(&client->dev, "irq %d busy?\n", client->irq); | ||
255 | goto err_unreg_dev; | ||
256 | } | ||
257 | |||
258 | error = adp5588_setup(client); | ||
259 | if (error) | ||
260 | goto err_free_irq; | ||
261 | |||
262 | device_init_wakeup(&client->dev, 1); | ||
263 | i2c_set_clientdata(client, kpad); | ||
264 | |||
265 | dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); | ||
266 | return 0; | ||
267 | |||
268 | err_free_irq: | ||
269 | free_irq(client->irq, kpad); | ||
270 | err_unreg_dev: | ||
271 | input_unregister_device(input); | ||
272 | input = NULL; | ||
273 | err_free_mem: | ||
274 | input_free_device(input); | ||
275 | kfree(kpad); | ||
276 | |||
277 | return error; | ||
278 | } | ||
279 | |||
280 | static int __devexit adp5588_remove(struct i2c_client *client) | ||
281 | { | ||
282 | struct adp5588_kpad *kpad = i2c_get_clientdata(client); | ||
283 | |||
284 | adp5588_write(client, CFG, 0); | ||
285 | free_irq(client->irq, kpad); | ||
286 | cancel_delayed_work_sync(&kpad->work); | ||
287 | input_unregister_device(kpad->input); | ||
288 | i2c_set_clientdata(client, NULL); | ||
289 | kfree(kpad); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | #ifdef CONFIG_PM | ||
295 | static int adp5588_suspend(struct device *dev) | ||
296 | { | ||
297 | struct adp5588_kpad *kpad = dev_get_drvdata(dev); | ||
298 | struct i2c_client *client = kpad->client; | ||
299 | |||
300 | disable_irq(client->irq); | ||
301 | cancel_delayed_work_sync(&kpad->work); | ||
302 | |||
303 | if (device_may_wakeup(&client->dev)) | ||
304 | enable_irq_wake(client->irq); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static int adp5588_resume(struct device *dev) | ||
310 | { | ||
311 | struct adp5588_kpad *kpad = dev_get_drvdata(dev); | ||
312 | struct i2c_client *client = kpad->client; | ||
313 | |||
314 | if (device_may_wakeup(&client->dev)) | ||
315 | disable_irq_wake(client->irq); | ||
316 | |||
317 | enable_irq(client->irq); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static struct dev_pm_ops adp5588_dev_pm_ops = { | ||
323 | .suspend = adp5588_suspend, | ||
324 | .resume = adp5588_resume, | ||
325 | }; | ||
326 | #endif | ||
327 | |||
328 | static const struct i2c_device_id adp5588_id[] = { | ||
329 | { KBUILD_MODNAME, 0 }, | ||
330 | { } | ||
331 | }; | ||
332 | MODULE_DEVICE_TABLE(i2c, adp5588_id); | ||
333 | |||
334 | static struct i2c_driver adp5588_driver = { | ||
335 | .driver = { | ||
336 | .name = KBUILD_MODNAME, | ||
337 | #ifdef CONFIG_PM | ||
338 | .pm = &adp5588_dev_pm_ops, | ||
339 | #endif | ||
340 | }, | ||
341 | .probe = adp5588_probe, | ||
342 | .remove = __devexit_p(adp5588_remove), | ||
343 | .id_table = adp5588_id, | ||
344 | }; | ||
345 | |||
346 | static int __init adp5588_init(void) | ||
347 | { | ||
348 | return i2c_add_driver(&adp5588_driver); | ||
349 | } | ||
350 | module_init(adp5588_init); | ||
351 | |||
352 | static void __exit adp5588_exit(void) | ||
353 | { | ||
354 | i2c_del_driver(&adp5588_driver); | ||
355 | } | ||
356 | module_exit(adp5588_exit); | ||
357 | |||
358 | MODULE_LICENSE("GPL"); | ||
359 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
360 | MODULE_DESCRIPTION("ADP5588 Keypad driver"); | ||
361 | MODULE_ALIAS("platform:adp5588-keys"); | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index adb09e2ba394..4709e15af607 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -773,23 +773,6 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra | |||
773 | static int atkbd_activate(struct atkbd *atkbd) | 773 | static int atkbd_activate(struct atkbd *atkbd) |
774 | { | 774 | { |
775 | struct ps2dev *ps2dev = &atkbd->ps2dev; | 775 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
776 | unsigned char param[1]; | ||
777 | |||
778 | /* | ||
779 | * Set the LEDs to a defined state. | ||
780 | */ | ||
781 | |||
782 | param[0] = 0; | ||
783 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) | ||
784 | return -1; | ||
785 | |||
786 | /* | ||
787 | * Set autorepeat to fastest possible. | ||
788 | */ | ||
789 | |||
790 | param[0] = 0; | ||
791 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP)) | ||
792 | return -1; | ||
793 | 776 | ||
794 | /* | 777 | /* |
795 | * Enable the keyboard to receive keystrokes. | 778 | * Enable the keyboard to receive keystrokes. |
@@ -1158,14 +1141,6 @@ static int atkbd_reconnect(struct serio *serio) | |||
1158 | return -1; | 1141 | return -1; |
1159 | 1142 | ||
1160 | atkbd_activate(atkbd); | 1143 | atkbd_activate(atkbd); |
1161 | |||
1162 | /* | ||
1163 | * Restore repeat rate and LEDs (that were reset by atkbd_activate) | ||
1164 | * to pre-resume state | ||
1165 | */ | ||
1166 | if (!atkbd->softrepeat) | ||
1167 | atkbd_set_repeat_rate(atkbd); | ||
1168 | atkbd_set_leds(atkbd); | ||
1169 | } | 1144 | } |
1170 | 1145 | ||
1171 | atkbd_enable(atkbd); | 1146 | atkbd_enable(atkbd); |
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c new file mode 100644 index 000000000000..3b5b948eba39 --- /dev/null +++ b/drivers/input/keyboard/max7359_keypad.c | |||
@@ -0,0 +1,330 @@ | |||
1 | /* | ||
2 | * max7359_keypad.c - MAX7359 Key Switch Controller Driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics | ||
5 | * Kim Kyuwon <q1.kim@samsung.com> | ||
6 | * | ||
7 | * Based on pxa27x_keypad.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/5456 | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/input.h> | ||
20 | #include <linux/input/matrix_keypad.h> | ||
21 | |||
22 | #define MAX7359_MAX_KEY_ROWS 8 | ||
23 | #define MAX7359_MAX_KEY_COLS 8 | ||
24 | #define MAX7359_MAX_KEY_NUM (MAX7359_MAX_KEY_ROWS * MAX7359_MAX_KEY_COLS) | ||
25 | #define MAX7359_ROW_SHIFT 3 | ||
26 | |||
27 | /* | ||
28 | * MAX7359 registers | ||
29 | */ | ||
30 | #define MAX7359_REG_KEYFIFO 0x00 | ||
31 | #define MAX7359_REG_CONFIG 0x01 | ||
32 | #define MAX7359_REG_DEBOUNCE 0x02 | ||
33 | #define MAX7359_REG_INTERRUPT 0x03 | ||
34 | #define MAX7359_REG_PORTS 0x04 | ||
35 | #define MAX7359_REG_KEYREP 0x05 | ||
36 | #define MAX7359_REG_SLEEP 0x06 | ||
37 | |||
38 | /* | ||
39 | * Configuration register bits | ||
40 | */ | ||
41 | #define MAX7359_CFG_SLEEP (1 << 7) | ||
42 | #define MAX7359_CFG_INTERRUPT (1 << 5) | ||
43 | #define MAX7359_CFG_KEY_RELEASE (1 << 3) | ||
44 | #define MAX7359_CFG_WAKEUP (1 << 1) | ||
45 | #define MAX7359_CFG_TIMEOUT (1 << 0) | ||
46 | |||
47 | /* | ||
48 | * Autosleep register values (ms) | ||
49 | */ | ||
50 | #define MAX7359_AUTOSLEEP_8192 0x01 | ||
51 | #define MAX7359_AUTOSLEEP_4096 0x02 | ||
52 | #define MAX7359_AUTOSLEEP_2048 0x03 | ||
53 | #define MAX7359_AUTOSLEEP_1024 0x04 | ||
54 | #define MAX7359_AUTOSLEEP_512 0x05 | ||
55 | #define MAX7359_AUTOSLEEP_256 0x06 | ||
56 | |||
57 | struct max7359_keypad { | ||
58 | /* matrix key code map */ | ||
59 | unsigned short keycodes[MAX7359_MAX_KEY_NUM]; | ||
60 | |||
61 | struct input_dev *input_dev; | ||
62 | struct i2c_client *client; | ||
63 | }; | ||
64 | |||
65 | static int max7359_write_reg(struct i2c_client *client, u8 reg, u8 val) | ||
66 | { | ||
67 | int ret = i2c_smbus_write_byte_data(client, reg, val); | ||
68 | |||
69 | if (ret < 0) | ||
70 | dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", | ||
71 | __func__, reg, val, ret); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | static int max7359_read_reg(struct i2c_client *client, int reg) | ||
76 | { | ||
77 | int ret = i2c_smbus_read_byte_data(client, reg); | ||
78 | |||
79 | if (ret < 0) | ||
80 | dev_err(&client->dev, "%s: reg 0x%x, err %d\n", | ||
81 | __func__, reg, ret); | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static void max7359_build_keycode(struct max7359_keypad *keypad, | ||
86 | const struct matrix_keymap_data *keymap_data) | ||
87 | { | ||
88 | struct input_dev *input_dev = keypad->input_dev; | ||
89 | int i; | ||
90 | |||
91 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
92 | unsigned int key = keymap_data->keymap[i]; | ||
93 | unsigned int row = KEY_ROW(key); | ||
94 | unsigned int col = KEY_COL(key); | ||
95 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, | ||
96 | MAX7359_ROW_SHIFT); | ||
97 | unsigned short keycode = KEY_VAL(key); | ||
98 | |||
99 | keypad->keycodes[scancode] = keycode; | ||
100 | __set_bit(keycode, input_dev->keybit); | ||
101 | } | ||
102 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
103 | } | ||
104 | |||
105 | /* runs in an IRQ thread -- can (and will!) sleep */ | ||
106 | static irqreturn_t max7359_interrupt(int irq, void *dev_id) | ||
107 | { | ||
108 | struct max7359_keypad *keypad = dev_id; | ||
109 | struct input_dev *input_dev = keypad->input_dev; | ||
110 | int val, row, col, release, code; | ||
111 | |||
112 | val = max7359_read_reg(keypad->client, MAX7359_REG_KEYFIFO); | ||
113 | row = val & 0x7; | ||
114 | col = (val >> 3) & 0x7; | ||
115 | release = val & 0x40; | ||
116 | |||
117 | code = MATRIX_SCAN_CODE(row, col, MAX7359_ROW_SHIFT); | ||
118 | |||
119 | dev_dbg(&keypad->client->dev, | ||
120 | "key[%d:%d] %s\n", row, col, release ? "release" : "press"); | ||
121 | |||
122 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
123 | input_report_key(input_dev, keypad->keycodes[code], !release); | ||
124 | input_sync(input_dev); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Let MAX7359 fall into a deep sleep: | ||
131 | * If no keys are pressed, enter sleep mode for 8192 ms. And if any | ||
132 | * key is pressed, the MAX7359 returns to normal operating mode. | ||
133 | */ | ||
134 | static inline void max7359_fall_deepsleep(struct i2c_client *client) | ||
135 | { | ||
136 | max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_8192); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * Let MAX7359 take a catnap: | ||
141 | * Autosleep just for 256 ms. | ||
142 | */ | ||
143 | static inline void max7359_take_catnap(struct i2c_client *client) | ||
144 | { | ||
145 | max7359_write_reg(client, MAX7359_REG_SLEEP, MAX7359_AUTOSLEEP_256); | ||
146 | } | ||
147 | |||
148 | static int max7359_open(struct input_dev *dev) | ||
149 | { | ||
150 | struct max7359_keypad *keypad = input_get_drvdata(dev); | ||
151 | |||
152 | max7359_take_catnap(keypad->client); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void max7359_close(struct input_dev *dev) | ||
158 | { | ||
159 | struct max7359_keypad *keypad = input_get_drvdata(dev); | ||
160 | |||
161 | max7359_fall_deepsleep(keypad->client); | ||
162 | } | ||
163 | |||
164 | static void max7359_initialize(struct i2c_client *client) | ||
165 | { | ||
166 | max7359_write_reg(client, MAX7359_REG_CONFIG, | ||
167 | MAX7359_CFG_INTERRUPT | /* Irq clears after host read */ | ||
168 | MAX7359_CFG_KEY_RELEASE | /* Key release enable */ | ||
169 | MAX7359_CFG_WAKEUP); /* Key press wakeup enable */ | ||
170 | |||
171 | /* Full key-scan functionality */ | ||
172 | max7359_write_reg(client, MAX7359_REG_DEBOUNCE, 0x1F); | ||
173 | |||
174 | /* nINT asserts every debounce cycles */ | ||
175 | max7359_write_reg(client, MAX7359_REG_INTERRUPT, 0x01); | ||
176 | |||
177 | max7359_fall_deepsleep(client); | ||
178 | } | ||
179 | |||
180 | static int __devinit max7359_probe(struct i2c_client *client, | ||
181 | const struct i2c_device_id *id) | ||
182 | { | ||
183 | const struct matrix_keymap_data *keymap_data = client->dev.platform_data; | ||
184 | struct max7359_keypad *keypad; | ||
185 | struct input_dev *input_dev; | ||
186 | int ret; | ||
187 | int error; | ||
188 | |||
189 | if (!client->irq) { | ||
190 | dev_err(&client->dev, "The irq number should not be zero\n"); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | /* Detect MAX7359: The initial Keys FIFO value is '0x3F' */ | ||
195 | ret = max7359_read_reg(client, MAX7359_REG_KEYFIFO); | ||
196 | if (ret < 0) { | ||
197 | dev_err(&client->dev, "failed to detect device\n"); | ||
198 | return -ENODEV; | ||
199 | } | ||
200 | |||
201 | dev_dbg(&client->dev, "keys FIFO is 0x%02x\n", ret); | ||
202 | |||
203 | keypad = kzalloc(sizeof(struct max7359_keypad), GFP_KERNEL); | ||
204 | input_dev = input_allocate_device(); | ||
205 | if (!keypad || !input_dev) { | ||
206 | dev_err(&client->dev, "failed to allocate memory\n"); | ||
207 | error = -ENOMEM; | ||
208 | goto failed_free_mem; | ||
209 | } | ||
210 | |||
211 | keypad->client = client; | ||
212 | keypad->input_dev = input_dev; | ||
213 | |||
214 | input_dev->name = client->name; | ||
215 | input_dev->id.bustype = BUS_I2C; | ||
216 | input_dev->open = max7359_open; | ||
217 | input_dev->close = max7359_close; | ||
218 | input_dev->dev.parent = &client->dev; | ||
219 | |||
220 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
221 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
222 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
223 | input_dev->keycode = keypad->keycodes; | ||
224 | |||
225 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
226 | input_set_drvdata(input_dev, keypad); | ||
227 | |||
228 | max7359_build_keycode(keypad, keymap_data); | ||
229 | |||
230 | error = request_threaded_irq(client->irq, NULL, max7359_interrupt, | ||
231 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
232 | client->name, keypad); | ||
233 | if (error) { | ||
234 | dev_err(&client->dev, "failed to register interrupt\n"); | ||
235 | goto failed_free_mem; | ||
236 | } | ||
237 | |||
238 | /* Register the input device */ | ||
239 | error = input_register_device(input_dev); | ||
240 | if (error) { | ||
241 | dev_err(&client->dev, "failed to register input device\n"); | ||
242 | goto failed_free_irq; | ||
243 | } | ||
244 | |||
245 | /* Initialize MAX7359 */ | ||
246 | max7359_initialize(client); | ||
247 | |||
248 | i2c_set_clientdata(client, keypad); | ||
249 | device_init_wakeup(&client->dev, 1); | ||
250 | |||
251 | return 0; | ||
252 | |||
253 | failed_free_irq: | ||
254 | free_irq(client->irq, keypad); | ||
255 | failed_free_mem: | ||
256 | input_free_device(input_dev); | ||
257 | kfree(keypad); | ||
258 | return error; | ||
259 | } | ||
260 | |||
261 | static int __devexit max7359_remove(struct i2c_client *client) | ||
262 | { | ||
263 | struct max7359_keypad *keypad = i2c_get_clientdata(client); | ||
264 | |||
265 | free_irq(client->irq, keypad); | ||
266 | input_unregister_device(keypad->input_dev); | ||
267 | i2c_set_clientdata(client, NULL); | ||
268 | kfree(keypad); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | #ifdef CONFIG_PM | ||
274 | static int max7359_suspend(struct i2c_client *client, pm_message_t mesg) | ||
275 | { | ||
276 | max7359_fall_deepsleep(client); | ||
277 | |||
278 | if (device_may_wakeup(&client->dev)) | ||
279 | enable_irq_wake(client->irq); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int max7359_resume(struct i2c_client *client) | ||
285 | { | ||
286 | if (device_may_wakeup(&client->dev)) | ||
287 | disable_irq_wake(client->irq); | ||
288 | |||
289 | /* Restore the default setting */ | ||
290 | max7359_take_catnap(client); | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | #else | ||
295 | #define max7359_suspend NULL | ||
296 | #define max7359_resume NULL | ||
297 | #endif | ||
298 | |||
299 | static const struct i2c_device_id max7359_ids[] = { | ||
300 | { "max7359", 0 }, | ||
301 | { } | ||
302 | }; | ||
303 | MODULE_DEVICE_TABLE(i2c, max7359_ids); | ||
304 | |||
305 | static struct i2c_driver max7359_i2c_driver = { | ||
306 | .driver = { | ||
307 | .name = "max7359", | ||
308 | }, | ||
309 | .probe = max7359_probe, | ||
310 | .remove = __devexit_p(max7359_remove), | ||
311 | .suspend = max7359_suspend, | ||
312 | .resume = max7359_resume, | ||
313 | .id_table = max7359_ids, | ||
314 | }; | ||
315 | |||
316 | static int __init max7359_init(void) | ||
317 | { | ||
318 | return i2c_add_driver(&max7359_i2c_driver); | ||
319 | } | ||
320 | module_init(max7359_init); | ||
321 | |||
322 | static void __exit max7359_exit(void) | ||
323 | { | ||
324 | i2c_del_driver(&max7359_i2c_driver); | ||
325 | } | ||
326 | module_exit(max7359_exit); | ||
327 | |||
328 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | ||
329 | MODULE_DESCRIPTION("MAX7359 Key Switch Controller Driver"); | ||
330 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c new file mode 100644 index 000000000000..78cccddbf551 --- /dev/null +++ b/drivers/input/keyboard/opencores-kbd.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * OpenCores Keyboard Controller Driver | ||
3 | * http://www.opencores.org/project,keyboardcontroller | ||
4 | * | ||
5 | * Copyright 2007-2009 HV Sistemas S.L. | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/input.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/ioport.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | |||
18 | struct opencores_kbd { | ||
19 | struct input_dev *input; | ||
20 | struct resource *addr_res; | ||
21 | void __iomem *addr; | ||
22 | int irq; | ||
23 | unsigned short keycodes[128]; | ||
24 | }; | ||
25 | |||
26 | static irqreturn_t opencores_kbd_isr(int irq, void *dev_id) | ||
27 | { | ||
28 | struct opencores_kbd *opencores_kbd = dev_id; | ||
29 | struct input_dev *input = opencores_kbd->input; | ||
30 | unsigned char c; | ||
31 | |||
32 | c = readb(opencores_kbd->addr); | ||
33 | input_report_key(input, c & 0x7f, c & 0x80 ? 0 : 1); | ||
34 | input_sync(input); | ||
35 | |||
36 | return IRQ_HANDLED; | ||
37 | } | ||
38 | |||
39 | static int __devinit opencores_kbd_probe(struct platform_device *pdev) | ||
40 | { | ||
41 | struct input_dev *input; | ||
42 | struct opencores_kbd *opencores_kbd; | ||
43 | struct resource *res; | ||
44 | int irq, i, error; | ||
45 | |||
46 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
47 | if (!res) { | ||
48 | dev_err(&pdev->dev, "missing board memory resource\n"); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | |||
52 | irq = platform_get_irq(pdev, 0); | ||
53 | if (irq < 0) { | ||
54 | dev_err(&pdev->dev, "missing board IRQ resource\n"); | ||
55 | return -EINVAL; | ||
56 | } | ||
57 | |||
58 | opencores_kbd = kzalloc(sizeof(*opencores_kbd), GFP_KERNEL); | ||
59 | input = input_allocate_device(); | ||
60 | if (!opencores_kbd || !input) { | ||
61 | dev_err(&pdev->dev, "failed to allocate device structures\n"); | ||
62 | error = -ENOMEM; | ||
63 | goto err_free_mem; | ||
64 | } | ||
65 | |||
66 | opencores_kbd->addr_res = res; | ||
67 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
68 | if (!res) { | ||
69 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
70 | error = -EBUSY; | ||
71 | goto err_free_mem; | ||
72 | } | ||
73 | |||
74 | opencores_kbd->addr = ioremap(res->start, resource_size(res)); | ||
75 | if (!opencores_kbd->addr) { | ||
76 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
77 | error = -ENXIO; | ||
78 | goto err_rel_mem; | ||
79 | } | ||
80 | |||
81 | opencores_kbd->input = input; | ||
82 | opencores_kbd->irq = irq; | ||
83 | |||
84 | input->name = pdev->name; | ||
85 | input->phys = "opencores-kbd/input0"; | ||
86 | input->dev.parent = &pdev->dev; | ||
87 | |||
88 | input_set_drvdata(input, opencores_kbd); | ||
89 | |||
90 | input->id.bustype = BUS_HOST; | ||
91 | input->id.vendor = 0x0001; | ||
92 | input->id.product = 0x0001; | ||
93 | input->id.version = 0x0100; | ||
94 | |||
95 | input->keycode = opencores_kbd->keycodes; | ||
96 | input->keycodesize = sizeof(opencores_kbd->keycodes[0]); | ||
97 | input->keycodemax = ARRAY_SIZE(opencores_kbd->keycodes); | ||
98 | |||
99 | __set_bit(EV_KEY, input->evbit); | ||
100 | |||
101 | for (i = 0; i < ARRAY_SIZE(opencores_kbd->keycodes); i++) { | ||
102 | /* | ||
103 | * OpenCores controller happens to have scancodes match | ||
104 | * our KEY_* definitions. | ||
105 | */ | ||
106 | opencores_kbd->keycodes[i] = i; | ||
107 | __set_bit(opencores_kbd->keycodes[i], input->keybit); | ||
108 | } | ||
109 | __clear_bit(KEY_RESERVED, input->keybit); | ||
110 | |||
111 | error = request_irq(irq, &opencores_kbd_isr, | ||
112 | IRQF_TRIGGER_RISING, pdev->name, opencores_kbd); | ||
113 | if (error) { | ||
114 | dev_err(&pdev->dev, "unable to claim irq %d\n", irq); | ||
115 | goto err_unmap_mem; | ||
116 | } | ||
117 | |||
118 | error = input_register_device(input); | ||
119 | if (error) { | ||
120 | dev_err(&pdev->dev, "unable to register input device\n"); | ||
121 | goto err_free_irq; | ||
122 | } | ||
123 | |||
124 | platform_set_drvdata(pdev, opencores_kbd); | ||
125 | |||
126 | return 0; | ||
127 | |||
128 | err_free_irq: | ||
129 | free_irq(irq, opencores_kbd); | ||
130 | err_unmap_mem: | ||
131 | iounmap(opencores_kbd->addr); | ||
132 | err_rel_mem: | ||
133 | release_mem_region(res->start, resource_size(res)); | ||
134 | err_free_mem: | ||
135 | input_free_device(input); | ||
136 | kfree(opencores_kbd); | ||
137 | |||
138 | return error; | ||
139 | } | ||
140 | |||
141 | static int __devexit opencores_kbd_remove(struct platform_device *pdev) | ||
142 | { | ||
143 | struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev); | ||
144 | |||
145 | free_irq(opencores_kbd->irq, opencores_kbd); | ||
146 | |||
147 | iounmap(opencores_kbd->addr); | ||
148 | release_mem_region(opencores_kbd->addr_res->start, | ||
149 | resource_size(opencores_kbd->addr_res)); | ||
150 | input_unregister_device(opencores_kbd->input); | ||
151 | kfree(opencores_kbd); | ||
152 | |||
153 | platform_set_drvdata(pdev, NULL); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct platform_driver opencores_kbd_device_driver = { | ||
159 | .probe = opencores_kbd_probe, | ||
160 | .remove = __devexit_p(opencores_kbd_remove), | ||
161 | .driver = { | ||
162 | .name = "opencores-kbd", | ||
163 | }, | ||
164 | }; | ||
165 | |||
166 | static int __init opencores_kbd_init(void) | ||
167 | { | ||
168 | return platform_driver_register(&opencores_kbd_device_driver); | ||
169 | } | ||
170 | module_init(opencores_kbd_init); | ||
171 | |||
172 | static void __exit opencores_kbd_exit(void) | ||
173 | { | ||
174 | platform_driver_unregister(&opencores_kbd_device_driver); | ||
175 | } | ||
176 | module_exit(opencores_kbd_exit); | ||
177 | |||
178 | MODULE_LICENSE("GPL"); | ||
179 | MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>"); | ||
180 | MODULE_DESCRIPTION("Keyboard driver for OpenCores Keyboard Controller"); | ||
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c new file mode 100644 index 000000000000..191cc51d6cf8 --- /dev/null +++ b/drivers/input/keyboard/qt2160.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * qt2160.c - Atmel AT42QT2160 Touch Sense Controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/jiffies.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/input.h> | ||
30 | |||
31 | #define QT2160_VALID_CHIPID 0x11 | ||
32 | |||
33 | #define QT2160_CMD_CHIPID 0 | ||
34 | #define QT2160_CMD_CODEVER 1 | ||
35 | #define QT2160_CMD_GSTAT 2 | ||
36 | #define QT2160_CMD_KEYS3 3 | ||
37 | #define QT2160_CMD_KEYS4 4 | ||
38 | #define QT2160_CMD_SLIDE 5 | ||
39 | #define QT2160_CMD_GPIOS 6 | ||
40 | #define QT2160_CMD_SUBVER 7 | ||
41 | #define QT2160_CMD_CALIBRATE 10 | ||
42 | |||
43 | #define QT2160_CYCLE_INTERVAL (2*HZ) | ||
44 | |||
45 | static unsigned char qt2160_key2code[] = { | ||
46 | KEY_0, KEY_1, KEY_2, KEY_3, | ||
47 | KEY_4, KEY_5, KEY_6, KEY_7, | ||
48 | KEY_8, KEY_9, KEY_A, KEY_B, | ||
49 | KEY_C, KEY_D, KEY_E, KEY_F, | ||
50 | }; | ||
51 | |||
52 | struct qt2160_data { | ||
53 | struct i2c_client *client; | ||
54 | struct input_dev *input; | ||
55 | struct delayed_work dwork; | ||
56 | spinlock_t lock; /* Protects canceling/rescheduling of dwork */ | ||
57 | unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; | ||
58 | u16 key_matrix; | ||
59 | }; | ||
60 | |||
61 | static int qt2160_read_block(struct i2c_client *client, | ||
62 | u8 inireg, u8 *buffer, unsigned int count) | ||
63 | { | ||
64 | int error, idx = 0; | ||
65 | |||
66 | /* | ||
67 | * Can't use SMBus block data read. Check for I2C functionality to speed | ||
68 | * things up whenever possible. Otherwise we will be forced to read | ||
69 | * sequentially. | ||
70 | */ | ||
71 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
72 | |||
73 | error = i2c_smbus_write_byte(client, inireg + idx); | ||
74 | if (error) { | ||
75 | dev_err(&client->dev, | ||
76 | "couldn't send request. Returned %d\n", error); | ||
77 | return error; | ||
78 | } | ||
79 | |||
80 | error = i2c_master_recv(client, buffer, count); | ||
81 | if (error != count) { | ||
82 | dev_err(&client->dev, | ||
83 | "couldn't read registers. Returned %d bytes\n", error); | ||
84 | return error; | ||
85 | } | ||
86 | } else { | ||
87 | |||
88 | while (count--) { | ||
89 | int data; | ||
90 | |||
91 | error = i2c_smbus_write_byte(client, inireg + idx); | ||
92 | if (error) { | ||
93 | dev_err(&client->dev, | ||
94 | "couldn't send request. Returned %d\n", error); | ||
95 | return error; | ||
96 | } | ||
97 | |||
98 | data = i2c_smbus_read_byte(client); | ||
99 | if (data < 0) { | ||
100 | dev_err(&client->dev, | ||
101 | "couldn't read register. Returned %d\n", data); | ||
102 | return data; | ||
103 | } | ||
104 | |||
105 | buffer[idx++] = data; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int qt2160_get_key_matrix(struct qt2160_data *qt2160) | ||
113 | { | ||
114 | struct i2c_client *client = qt2160->client; | ||
115 | struct input_dev *input = qt2160->input; | ||
116 | u8 regs[6]; | ||
117 | u16 old_matrix, new_matrix; | ||
118 | int ret, i, mask; | ||
119 | |||
120 | dev_dbg(&client->dev, "requesting keys...\n"); | ||
121 | |||
122 | /* | ||
123 | * Read all registers from General Status Register | ||
124 | * to GPIOs register | ||
125 | */ | ||
126 | ret = qt2160_read_block(client, QT2160_CMD_GSTAT, regs, 6); | ||
127 | if (ret) { | ||
128 | dev_err(&client->dev, | ||
129 | "could not perform chip read.\n"); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | old_matrix = qt2160->key_matrix; | ||
134 | qt2160->key_matrix = new_matrix = (regs[2] << 8) | regs[1]; | ||
135 | |||
136 | mask = 0x01; | ||
137 | for (i = 0; i < 16; ++i, mask <<= 1) { | ||
138 | int keyval = new_matrix & mask; | ||
139 | |||
140 | if ((old_matrix & mask) != keyval) { | ||
141 | input_report_key(input, qt2160->keycodes[i], keyval); | ||
142 | dev_dbg(&client->dev, "key %d %s\n", | ||
143 | i, keyval ? "pressed" : "released"); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | input_sync(input); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static irqreturn_t qt2160_irq(int irq, void *_qt2160) | ||
153 | { | ||
154 | struct qt2160_data *qt2160 = _qt2160; | ||
155 | unsigned long flags; | ||
156 | |||
157 | spin_lock_irqsave(&qt2160->lock, flags); | ||
158 | |||
159 | __cancel_delayed_work(&qt2160->dwork); | ||
160 | schedule_delayed_work(&qt2160->dwork, 0); | ||
161 | |||
162 | spin_unlock_irqrestore(&qt2160->lock, flags); | ||
163 | |||
164 | return IRQ_HANDLED; | ||
165 | } | ||
166 | |||
167 | static void qt2160_schedule_read(struct qt2160_data *qt2160) | ||
168 | { | ||
169 | spin_lock_irq(&qt2160->lock); | ||
170 | schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL); | ||
171 | spin_unlock_irq(&qt2160->lock); | ||
172 | } | ||
173 | |||
174 | static void qt2160_worker(struct work_struct *work) | ||
175 | { | ||
176 | struct qt2160_data *qt2160 = | ||
177 | container_of(work, struct qt2160_data, dwork.work); | ||
178 | |||
179 | dev_dbg(&qt2160->client->dev, "worker\n"); | ||
180 | |||
181 | qt2160_get_key_matrix(qt2160); | ||
182 | |||
183 | /* Avoid device lock up by checking every so often */ | ||
184 | qt2160_schedule_read(qt2160); | ||
185 | } | ||
186 | |||
187 | static int __devinit qt2160_read(struct i2c_client *client, u8 reg) | ||
188 | { | ||
189 | int ret; | ||
190 | |||
191 | ret = i2c_smbus_write_byte(client, reg); | ||
192 | if (ret) { | ||
193 | dev_err(&client->dev, | ||
194 | "couldn't send request. Returned %d\n", ret); | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | ret = i2c_smbus_read_byte(client); | ||
199 | if (ret < 0) { | ||
200 | dev_err(&client->dev, | ||
201 | "couldn't read register. Returned %d\n", ret); | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data) | ||
209 | { | ||
210 | int error; | ||
211 | |||
212 | error = i2c_smbus_write_byte(client, reg); | ||
213 | if (error) { | ||
214 | dev_err(&client->dev, | ||
215 | "couldn't send request. Returned %d\n", error); | ||
216 | return error; | ||
217 | } | ||
218 | |||
219 | error = i2c_smbus_write_byte(client, data); | ||
220 | if (error) { | ||
221 | dev_err(&client->dev, | ||
222 | "couldn't write data. Returned %d\n", error); | ||
223 | return error; | ||
224 | } | ||
225 | |||
226 | return error; | ||
227 | } | ||
228 | |||
229 | |||
230 | static bool __devinit qt2160_identify(struct i2c_client *client) | ||
231 | { | ||
232 | int id, ver, rev; | ||
233 | |||
234 | /* Read Chid ID to check if chip is valid */ | ||
235 | id = qt2160_read(client, QT2160_CMD_CHIPID); | ||
236 | if (id != QT2160_VALID_CHIPID) { | ||
237 | dev_err(&client->dev, "ID %d not supported\n", id); | ||
238 | return false; | ||
239 | } | ||
240 | |||
241 | /* Read chip firmware version */ | ||
242 | ver = qt2160_read(client, QT2160_CMD_CODEVER); | ||
243 | if (ver < 0) { | ||
244 | dev_err(&client->dev, "could not get firmware version\n"); | ||
245 | return false; | ||
246 | } | ||
247 | |||
248 | /* Read chip firmware revision */ | ||
249 | rev = qt2160_read(client, QT2160_CMD_SUBVER); | ||
250 | if (rev < 0) { | ||
251 | dev_err(&client->dev, "could not get firmware revision\n"); | ||
252 | return false; | ||
253 | } | ||
254 | |||
255 | dev_info(&client->dev, "AT42QT2160 firmware version %d.%d.%d\n", | ||
256 | ver >> 4, ver & 0xf, rev); | ||
257 | |||
258 | return true; | ||
259 | } | ||
260 | |||
261 | static int __devinit qt2160_probe(struct i2c_client *client, | ||
262 | const struct i2c_device_id *id) | ||
263 | { | ||
264 | struct qt2160_data *qt2160; | ||
265 | struct input_dev *input; | ||
266 | int i; | ||
267 | int error; | ||
268 | |||
269 | /* Check functionality */ | ||
270 | error = i2c_check_functionality(client->adapter, | ||
271 | I2C_FUNC_SMBUS_BYTE); | ||
272 | if (!error) { | ||
273 | dev_err(&client->dev, "%s adapter not supported\n", | ||
274 | dev_driver_string(&client->adapter->dev)); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | |||
278 | if (!qt2160_identify(client)) | ||
279 | return -ENODEV; | ||
280 | |||
281 | /* Chip is valid and active. Allocate structure */ | ||
282 | qt2160 = kzalloc(sizeof(struct qt2160_data), GFP_KERNEL); | ||
283 | input = input_allocate_device(); | ||
284 | if (!qt2160 || !input) { | ||
285 | dev_err(&client->dev, "insufficient memory\n"); | ||
286 | error = -ENOMEM; | ||
287 | goto err_free_mem; | ||
288 | } | ||
289 | |||
290 | qt2160->client = client; | ||
291 | qt2160->input = input; | ||
292 | INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker); | ||
293 | spin_lock_init(&qt2160->lock); | ||
294 | |||
295 | input->name = "AT42QT2160 Touch Sense Keyboard"; | ||
296 | input->id.bustype = BUS_I2C; | ||
297 | |||
298 | input->keycode = qt2160->keycodes; | ||
299 | input->keycodesize = sizeof(qt2160->keycodes[0]); | ||
300 | input->keycodemax = ARRAY_SIZE(qt2160_key2code); | ||
301 | |||
302 | __set_bit(EV_KEY, input->evbit); | ||
303 | __clear_bit(EV_REP, input->evbit); | ||
304 | for (i = 0; i < ARRAY_SIZE(qt2160_key2code); i++) { | ||
305 | qt2160->keycodes[i] = qt2160_key2code[i]; | ||
306 | __set_bit(qt2160_key2code[i], input->keybit); | ||
307 | } | ||
308 | __clear_bit(KEY_RESERVED, input->keybit); | ||
309 | |||
310 | /* Calibrate device */ | ||
311 | error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1); | ||
312 | if (error) { | ||
313 | dev_err(&client->dev, "failed to calibrate device\n"); | ||
314 | goto err_free_mem; | ||
315 | } | ||
316 | |||
317 | if (client->irq) { | ||
318 | error = request_irq(client->irq, qt2160_irq, | ||
319 | IRQF_TRIGGER_FALLING, "qt2160", qt2160); | ||
320 | if (error) { | ||
321 | dev_err(&client->dev, | ||
322 | "failed to allocate irq %d\n", client->irq); | ||
323 | goto err_free_mem; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | error = input_register_device(qt2160->input); | ||
328 | if (error) { | ||
329 | dev_err(&client->dev, | ||
330 | "Failed to register input device\n"); | ||
331 | goto err_free_irq; | ||
332 | } | ||
333 | |||
334 | i2c_set_clientdata(client, qt2160); | ||
335 | qt2160_schedule_read(qt2160); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | err_free_irq: | ||
340 | if (client->irq) | ||
341 | free_irq(client->irq, qt2160); | ||
342 | err_free_mem: | ||
343 | input_free_device(input); | ||
344 | kfree(qt2160); | ||
345 | return error; | ||
346 | } | ||
347 | |||
348 | static int __devexit qt2160_remove(struct i2c_client *client) | ||
349 | { | ||
350 | struct qt2160_data *qt2160 = i2c_get_clientdata(client); | ||
351 | |||
352 | /* Release IRQ so no queue will be scheduled */ | ||
353 | if (client->irq) | ||
354 | free_irq(client->irq, qt2160); | ||
355 | |||
356 | cancel_delayed_work_sync(&qt2160->dwork); | ||
357 | |||
358 | input_unregister_device(qt2160->input); | ||
359 | kfree(qt2160); | ||
360 | |||
361 | i2c_set_clientdata(client, NULL); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static struct i2c_device_id qt2160_idtable[] = { | ||
366 | { "qt2160", 0, }, | ||
367 | { } | ||
368 | }; | ||
369 | |||
370 | MODULE_DEVICE_TABLE(i2c, qt2160_idtable); | ||
371 | |||
372 | static struct i2c_driver qt2160_driver = { | ||
373 | .driver = { | ||
374 | .name = "qt2160", | ||
375 | .owner = THIS_MODULE, | ||
376 | }, | ||
377 | |||
378 | .id_table = qt2160_idtable, | ||
379 | .probe = qt2160_probe, | ||
380 | .remove = __devexit_p(qt2160_remove), | ||
381 | }; | ||
382 | |||
383 | static int __init qt2160_init(void) | ||
384 | { | ||
385 | return i2c_add_driver(&qt2160_driver); | ||
386 | } | ||
387 | module_init(qt2160_init); | ||
388 | |||
389 | static void __exit qt2160_cleanup(void) | ||
390 | { | ||
391 | i2c_del_driver(&qt2160_driver); | ||
392 | } | ||
393 | module_exit(qt2160_cleanup); | ||
394 | |||
395 | MODULE_AUTHOR("Raphael Derosso Pereira <raphaelpereira@gmail.com>"); | ||
396 | MODULE_DESCRIPTION("Driver for AT42QT2160 Touch Sensor"); | ||
397 | MODULE_LICENSE("GPL"); | ||