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 | |
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')
-rw-r--r-- | drivers/input/input.c | 64 | ||||
-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 | ||||
-rw-r--r-- | drivers/input/misc/dm355evm_keys.c | 26 | ||||
-rw-r--r-- | drivers/input/mouse/sentelic.c | 18 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics_i2c.c | 51 | ||||
-rw-r--r-- | drivers/input/serio/i8042.c | 41 | ||||
-rw-r--r-- | drivers/input/serio/libps2.c | 28 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 17 | ||||
-rw-r--r-- | drivers/input/touchscreen/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.c | 6 | ||||
-rw-r--r-- | drivers/input/touchscreen/mcs5000_ts.c | 318 | ||||
-rw-r--r-- | drivers/leds/leds-clevo-mail.c | 8 | ||||
-rw-r--r-- | drivers/platform/x86/acer-wmi.c | 2 |
19 files changed, 1838 insertions, 79 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 556539d617a4..e828aab7dace 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/types.h> | ||
14 | #include <linux/input.h> | 15 | #include <linux/input.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/random.h> | 17 | #include <linux/random.h> |
@@ -514,7 +515,7 @@ static void input_disconnect_device(struct input_dev *dev) | |||
514 | * that there are no threads in the middle of input_open_device() | 515 | * that there are no threads in the middle of input_open_device() |
515 | */ | 516 | */ |
516 | mutex_lock(&dev->mutex); | 517 | mutex_lock(&dev->mutex); |
517 | dev->going_away = 1; | 518 | dev->going_away = true; |
518 | mutex_unlock(&dev->mutex); | 519 | mutex_unlock(&dev->mutex); |
519 | 520 | ||
520 | spin_lock_irq(&dev->event_lock); | 521 | spin_lock_irq(&dev->event_lock); |
@@ -1259,10 +1260,71 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) | |||
1259 | return 0; | 1260 | return 0; |
1260 | } | 1261 | } |
1261 | 1262 | ||
1263 | #define INPUT_DO_TOGGLE(dev, type, bits, on) \ | ||
1264 | do { \ | ||
1265 | int i; \ | ||
1266 | if (!test_bit(EV_##type, dev->evbit)) \ | ||
1267 | break; \ | ||
1268 | for (i = 0; i < type##_MAX; i++) { \ | ||
1269 | if (!test_bit(i, dev->bits##bit) || \ | ||
1270 | !test_bit(i, dev->bits)) \ | ||
1271 | continue; \ | ||
1272 | dev->event(dev, EV_##type, i, on); \ | ||
1273 | } \ | ||
1274 | } while (0) | ||
1275 | |||
1276 | static void input_dev_reset(struct input_dev *dev, bool activate) | ||
1277 | { | ||
1278 | if (!dev->event) | ||
1279 | return; | ||
1280 | |||
1281 | INPUT_DO_TOGGLE(dev, LED, led, activate); | ||
1282 | INPUT_DO_TOGGLE(dev, SND, snd, activate); | ||
1283 | |||
1284 | if (activate && test_bit(EV_REP, dev->evbit)) { | ||
1285 | dev->event(dev, EV_REP, REP_PERIOD, dev->rep[REP_PERIOD]); | ||
1286 | dev->event(dev, EV_REP, REP_DELAY, dev->rep[REP_DELAY]); | ||
1287 | } | ||
1288 | } | ||
1289 | |||
1290 | #ifdef CONFIG_PM | ||
1291 | static int input_dev_suspend(struct device *dev) | ||
1292 | { | ||
1293 | struct input_dev *input_dev = to_input_dev(dev); | ||
1294 | |||
1295 | mutex_lock(&input_dev->mutex); | ||
1296 | input_dev_reset(input_dev, false); | ||
1297 | mutex_unlock(&input_dev->mutex); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | static int input_dev_resume(struct device *dev) | ||
1303 | { | ||
1304 | struct input_dev *input_dev = to_input_dev(dev); | ||
1305 | |||
1306 | mutex_lock(&input_dev->mutex); | ||
1307 | input_dev_reset(input_dev, true); | ||
1308 | mutex_unlock(&input_dev->mutex); | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | static const struct dev_pm_ops input_dev_pm_ops = { | ||
1314 | .suspend = input_dev_suspend, | ||
1315 | .resume = input_dev_resume, | ||
1316 | .poweroff = input_dev_suspend, | ||
1317 | .restore = input_dev_resume, | ||
1318 | }; | ||
1319 | #endif /* CONFIG_PM */ | ||
1320 | |||
1262 | static struct device_type input_dev_type = { | 1321 | static struct device_type input_dev_type = { |
1263 | .groups = input_dev_attr_groups, | 1322 | .groups = input_dev_attr_groups, |
1264 | .release = input_dev_release, | 1323 | .release = input_dev_release, |
1265 | .uevent = input_dev_uevent, | 1324 | .uevent = input_dev_uevent, |
1325 | #ifdef CONFIG_PM | ||
1326 | .pm = &input_dev_pm_ops, | ||
1327 | #endif | ||
1266 | }; | 1328 | }; |
1267 | 1329 | ||
1268 | static char *input_devnode(struct device *dev, mode_t *mode) | 1330 | static char *input_devnode(struct device *dev, mode_t *mode) |
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"); | ||
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index 0918acae584a..f2b67dc81d80 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -96,7 +96,13 @@ static struct { | |||
96 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
97 | }; | 97 | }; |
98 | 98 | ||
99 | /* runs in an IRQ thread -- can (and will!) sleep */ | 99 | /* |
100 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
101 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
102 | * active low, but we go through the GPIO controller so we can trigger | ||
103 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
104 | * the keypress handling path. | ||
105 | */ | ||
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | 106 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) |
101 | { | 107 | { |
102 | struct dm355evm_keys *keys = _keys; | 108 | struct dm355evm_keys *keys = _keys; |
@@ -171,18 +177,6 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | |||
171 | return IRQ_HANDLED; | 177 | return IRQ_HANDLED; |
172 | } | 178 | } |
173 | 179 | ||
174 | /* | ||
175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
177 | * active low, but we go through the GPIO controller so we can trigger | ||
178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
179 | * the keypress handling path. | ||
180 | */ | ||
181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
182 | { | ||
183 | return IRQ_WAKE_THREAD; | ||
184 | } | ||
185 | |||
186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 180 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
187 | { | 181 | { |
188 | u16 old_keycode; | 182 | u16 old_keycode; |
@@ -257,10 +251,8 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
257 | 251 | ||
258 | /* REVISIT: flush the event queue? */ | 252 | /* REVISIT: flush the event queue? */ |
259 | 253 | ||
260 | status = request_threaded_irq(keys->irq, | 254 | status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq, |
261 | dm355evm_keys_hardirq, dm355evm_keys_irq, | 255 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys); |
262 | IRQF_TRIGGER_FALLING, | ||
263 | dev_name(&pdev->dev), keys); | ||
264 | if (status < 0) | 256 | if (status < 0) |
265 | goto fail1; | 257 | goto fail1; |
266 | 258 | ||
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 84e2fc04d11b..f84cbd97c884 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
@@ -92,7 +92,8 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
92 | */ | 92 | */ |
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
95 | mutex_lock(&ps2dev->cmd_mutex); | 95 | |
96 | ps2_begin_command(ps2dev); | ||
96 | 97 | ||
97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 98 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
98 | goto out; | 99 | goto out; |
@@ -126,7 +127,7 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | |||
126 | rc = 0; | 127 | rc = 0; |
127 | 128 | ||
128 | out: | 129 | out: |
129 | mutex_unlock(&ps2dev->cmd_mutex); | 130 | ps2_end_command(ps2dev); |
130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 131 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 132 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | 133 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", |
@@ -140,7 +141,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
140 | unsigned char v; | 141 | unsigned char v; |
141 | int rc = -1; | 142 | int rc = -1; |
142 | 143 | ||
143 | mutex_lock(&ps2dev->cmd_mutex); | 144 | ps2_begin_command(ps2dev); |
144 | 145 | ||
145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 146 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
146 | goto out; | 147 | goto out; |
@@ -179,7 +180,7 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | |||
179 | rc = 0; | 180 | rc = 0; |
180 | 181 | ||
181 | out: | 182 | out: |
182 | mutex_unlock(&ps2dev->cmd_mutex); | 183 | ps2_end_command(ps2dev); |
183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | 184 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", |
184 | reg_addr, reg_val, rc); | 185 | reg_addr, reg_val, rc); |
185 | return rc; | 186 | return rc; |
@@ -214,7 +215,8 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
214 | 215 | ||
215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | 216 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); |
216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 217 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
217 | mutex_lock(&ps2dev->cmd_mutex); | 218 | |
219 | ps2_begin_command(ps2dev); | ||
218 | 220 | ||
219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 221 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
220 | goto out; | 222 | goto out; |
@@ -236,7 +238,7 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | |||
236 | rc = 0; | 238 | rc = 0; |
237 | 239 | ||
238 | out: | 240 | out: |
239 | mutex_unlock(&ps2dev->cmd_mutex); | 241 | ps2_end_command(ps2dev); |
240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | 242 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); |
241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | 243 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); |
242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | 244 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", |
@@ -250,7 +252,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
250 | unsigned char v; | 252 | unsigned char v; |
251 | int rc = -1; | 253 | int rc = -1; |
252 | 254 | ||
253 | mutex_lock(&ps2dev->cmd_mutex); | 255 | ps2_begin_command(ps2dev); |
254 | 256 | ||
255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | 257 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) |
256 | goto out; | 258 | goto out; |
@@ -275,7 +277,7 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | |||
275 | rc = 0; | 277 | rc = 0; |
276 | 278 | ||
277 | out: | 279 | out: |
278 | mutex_unlock(&ps2dev->cmd_mutex); | 280 | ps2_end_command(ps2dev); |
279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | 281 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", |
280 | reg_val, rc); | 282 | reg_val, rc); |
281 | return rc; | 283 | return rc; |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index eac9fdde7ee9..7283c78044af 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
@@ -203,7 +203,7 @@ MODULE_PARM_DESC(no_filter, "No Filter. Default = 0 (off)"); | |||
203 | * and the irq configuration should be set to Falling Edge Trigger | 203 | * and the irq configuration should be set to Falling Edge Trigger |
204 | */ | 204 | */ |
205 | /* Control IRQ / Polling option */ | 205 | /* Control IRQ / Polling option */ |
206 | static int polling_req; | 206 | static bool polling_req; |
207 | module_param(polling_req, bool, 0444); | 207 | module_param(polling_req, bool, 0444); |
208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); | 208 | MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)"); |
209 | 209 | ||
@@ -217,6 +217,7 @@ struct synaptics_i2c { | |||
217 | struct i2c_client *client; | 217 | struct i2c_client *client; |
218 | struct input_dev *input; | 218 | struct input_dev *input; |
219 | struct delayed_work dwork; | 219 | struct delayed_work dwork; |
220 | spinlock_t lock; | ||
220 | int no_data_count; | 221 | int no_data_count; |
221 | int no_decel_param; | 222 | int no_decel_param; |
222 | int reduce_report_param; | 223 | int reduce_report_param; |
@@ -366,17 +367,28 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch) | |||
366 | return xy_delta || gesture; | 367 | return xy_delta || gesture; |
367 | } | 368 | } |
368 | 369 | ||
369 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | 370 | static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, |
371 | unsigned long delay) | ||
370 | { | 372 | { |
371 | struct synaptics_i2c *touch = dev_id; | 373 | unsigned long flags; |
374 | |||
375 | spin_lock_irqsave(&touch->lock, flags); | ||
372 | 376 | ||
373 | /* | 377 | /* |
374 | * We want to have the work run immediately but it might have | 378 | * If work is already scheduled then subsequent schedules will not |
375 | * already been scheduled with a delay, that's why we have to | 379 | * change the scheduled time that's why we have to cancel it first. |
376 | * cancel it first. | ||
377 | */ | 380 | */ |
378 | cancel_delayed_work(&touch->dwork); | 381 | __cancel_delayed_work(&touch->dwork); |
379 | schedule_delayed_work(&touch->dwork, 0); | 382 | schedule_delayed_work(&touch->dwork, delay); |
383 | |||
384 | spin_unlock_irqrestore(&touch->lock, flags); | ||
385 | } | ||
386 | |||
387 | static irqreturn_t synaptics_i2c_irq(int irq, void *dev_id) | ||
388 | { | ||
389 | struct synaptics_i2c *touch = dev_id; | ||
390 | |||
391 | synaptics_i2c_reschedule_work(touch, 0); | ||
380 | 392 | ||
381 | return IRQ_HANDLED; | 393 | return IRQ_HANDLED; |
382 | } | 394 | } |
@@ -452,7 +464,7 @@ static void synaptics_i2c_work_handler(struct work_struct *work) | |||
452 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and | 464 | * We poll the device once in THREAD_IRQ_SLEEP_SECS and |
453 | * if error is detected, we try to reset and reconfigure the touchpad. | 465 | * if error is detected, we try to reset and reconfigure the touchpad. |
454 | */ | 466 | */ |
455 | schedule_delayed_work(&touch->dwork, delay); | 467 | synaptics_i2c_reschedule_work(touch, delay); |
456 | } | 468 | } |
457 | 469 | ||
458 | static int synaptics_i2c_open(struct input_dev *input) | 470 | static int synaptics_i2c_open(struct input_dev *input) |
@@ -465,8 +477,8 @@ static int synaptics_i2c_open(struct input_dev *input) | |||
465 | return ret; | 477 | return ret; |
466 | 478 | ||
467 | if (polling_req) | 479 | if (polling_req) |
468 | schedule_delayed_work(&touch->dwork, | 480 | synaptics_i2c_reschedule_work(touch, |
469 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 481 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); |
470 | 482 | ||
471 | return 0; | 483 | return 0; |
472 | } | 484 | } |
@@ -521,6 +533,7 @@ struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | |||
521 | touch->scan_rate_param = scan_rate; | 533 | touch->scan_rate_param = scan_rate; |
522 | set_scan_rate(touch, scan_rate); | 534 | set_scan_rate(touch, scan_rate); |
523 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); | 535 | INIT_DELAYED_WORK(&touch->dwork, synaptics_i2c_work_handler); |
536 | spin_lock_init(&touch->lock); | ||
524 | 537 | ||
525 | return touch; | 538 | return touch; |
526 | } | 539 | } |
@@ -535,14 +548,12 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
535 | if (!touch) | 548 | if (!touch) |
536 | return -ENOMEM; | 549 | return -ENOMEM; |
537 | 550 | ||
538 | i2c_set_clientdata(client, touch); | ||
539 | |||
540 | ret = synaptics_i2c_reset_config(client); | 551 | ret = synaptics_i2c_reset_config(client); |
541 | if (ret) | 552 | if (ret) |
542 | goto err_mem_free; | 553 | goto err_mem_free; |
543 | 554 | ||
544 | if (client->irq < 1) | 555 | if (client->irq < 1) |
545 | polling_req = 1; | 556 | polling_req = true; |
546 | 557 | ||
547 | touch->input = input_allocate_device(); | 558 | touch->input = input_allocate_device(); |
548 | if (!touch->input) { | 559 | if (!touch->input) { |
@@ -563,7 +574,7 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
563 | dev_warn(&touch->client->dev, | 574 | dev_warn(&touch->client->dev, |
564 | "IRQ request failed: %d, " | 575 | "IRQ request failed: %d, " |
565 | "falling back to polling\n", ret); | 576 | "falling back to polling\n", ret); |
566 | polling_req = 1; | 577 | polling_req = true; |
567 | synaptics_i2c_reg_set(touch->client, | 578 | synaptics_i2c_reg_set(touch->client, |
568 | INTERRUPT_EN_REG, 0); | 579 | INTERRUPT_EN_REG, 0); |
569 | } | 580 | } |
@@ -580,12 +591,14 @@ static int __devinit synaptics_i2c_probe(struct i2c_client *client, | |||
580 | "Input device register failed: %d\n", ret); | 591 | "Input device register failed: %d\n", ret); |
581 | goto err_input_free; | 592 | goto err_input_free; |
582 | } | 593 | } |
594 | |||
595 | i2c_set_clientdata(client, touch); | ||
596 | |||
583 | return 0; | 597 | return 0; |
584 | 598 | ||
585 | err_input_free: | 599 | err_input_free: |
586 | input_free_device(touch->input); | 600 | input_free_device(touch->input); |
587 | err_mem_free: | 601 | err_mem_free: |
588 | i2c_set_clientdata(client, NULL); | ||
589 | kfree(touch); | 602 | kfree(touch); |
590 | 603 | ||
591 | return ret; | 604 | return ret; |
@@ -596,7 +609,7 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) | |||
596 | struct synaptics_i2c *touch = i2c_get_clientdata(client); | 609 | struct synaptics_i2c *touch = i2c_get_clientdata(client); |
597 | 610 | ||
598 | if (!polling_req) | 611 | if (!polling_req) |
599 | free_irq(touch->client->irq, touch); | 612 | free_irq(client->irq, touch); |
600 | 613 | ||
601 | input_unregister_device(touch->input); | 614 | input_unregister_device(touch->input); |
602 | i2c_set_clientdata(client, NULL); | 615 | i2c_set_clientdata(client, NULL); |
@@ -627,8 +640,8 @@ static int synaptics_i2c_resume(struct i2c_client *client) | |||
627 | if (ret) | 640 | if (ret) |
628 | return ret; | 641 | return ret; |
629 | 642 | ||
630 | schedule_delayed_work(&touch->dwork, | 643 | synaptics_i2c_reschedule_work(touch, |
631 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); | 644 | msecs_to_jiffies(NO_DATA_SLEEP_MSECS)); |
632 | 645 | ||
633 | return 0; | 646 | return 0; |
634 | } | 647 | } |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index eb3ff94af58c..bc56e52b945f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -87,8 +87,22 @@ static bool i8042_bypass_aux_irq_test; | |||
87 | 87 | ||
88 | #include "i8042.h" | 88 | #include "i8042.h" |
89 | 89 | ||
90 | /* | ||
91 | * i8042_lock protects serialization between i8042_command and | ||
92 | * the interrupt handler. | ||
93 | */ | ||
90 | static DEFINE_SPINLOCK(i8042_lock); | 94 | static DEFINE_SPINLOCK(i8042_lock); |
91 | 95 | ||
96 | /* | ||
97 | * Writers to AUX and KBD ports as well as users issuing i8042_command | ||
98 | * directly should acquire i8042_mutex (by means of calling | ||
99 | * i8042_lock_chip() and i8042_unlock_ship() helpers) to ensure that | ||
100 | * they do not disturb each other (unfortunately in many i8042 | ||
101 | * implementations write to one of the ports will immediately abort | ||
102 | * command that is being processed by another port). | ||
103 | */ | ||
104 | static DEFINE_MUTEX(i8042_mutex); | ||
105 | |||
92 | struct i8042_port { | 106 | struct i8042_port { |
93 | struct serio *serio; | 107 | struct serio *serio; |
94 | int irq; | 108 | int irq; |
@@ -113,6 +127,18 @@ static struct platform_device *i8042_platform_device; | |||
113 | 127 | ||
114 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); | 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); |
115 | 129 | ||
130 | void i8042_lock_chip(void) | ||
131 | { | ||
132 | mutex_lock(&i8042_mutex); | ||
133 | } | ||
134 | EXPORT_SYMBOL(i8042_lock_chip); | ||
135 | |||
136 | void i8042_unlock_chip(void) | ||
137 | { | ||
138 | mutex_unlock(&i8042_mutex); | ||
139 | } | ||
140 | EXPORT_SYMBOL(i8042_unlock_chip); | ||
141 | |||
116 | /* | 142 | /* |
117 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to | 143 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to |
118 | * be ready for reading values from it / writing values to it. | 144 | * be ready for reading values from it / writing values to it. |
@@ -1161,6 +1187,21 @@ static void __devexit i8042_unregister_ports(void) | |||
1161 | } | 1187 | } |
1162 | } | 1188 | } |
1163 | 1189 | ||
1190 | /* | ||
1191 | * Checks whether port belongs to i8042 controller. | ||
1192 | */ | ||
1193 | bool i8042_check_port_owner(const struct serio *port) | ||
1194 | { | ||
1195 | int i; | ||
1196 | |||
1197 | for (i = 0; i < I8042_NUM_PORTS; i++) | ||
1198 | if (i8042_ports[i].serio == port) | ||
1199 | return true; | ||
1200 | |||
1201 | return false; | ||
1202 | } | ||
1203 | EXPORT_SYMBOL(i8042_check_port_owner); | ||
1204 | |||
1164 | static void i8042_free_irqs(void) | 1205 | static void i8042_free_irqs(void) |
1165 | { | 1206 | { |
1166 | if (i8042_aux_irq_registered) | 1207 | if (i8042_aux_irq_registered) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 3a95b508bf27..769ba65a585a 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
20 | #include <linux/i8042.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/libps2.h> | 22 | #include <linux/libps2.h> |
22 | 23 | ||
@@ -54,6 +55,24 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
54 | } | 55 | } |
55 | EXPORT_SYMBOL(ps2_sendbyte); | 56 | EXPORT_SYMBOL(ps2_sendbyte); |
56 | 57 | ||
58 | void ps2_begin_command(struct ps2dev *ps2dev) | ||
59 | { | ||
60 | mutex_lock(&ps2dev->cmd_mutex); | ||
61 | |||
62 | if (i8042_check_port_owner(ps2dev->serio)) | ||
63 | i8042_lock_chip(); | ||
64 | } | ||
65 | EXPORT_SYMBOL(ps2_begin_command); | ||
66 | |||
67 | void ps2_end_command(struct ps2dev *ps2dev) | ||
68 | { | ||
69 | if (i8042_check_port_owner(ps2dev->serio)) | ||
70 | i8042_unlock_chip(); | ||
71 | |||
72 | mutex_unlock(&ps2dev->cmd_mutex); | ||
73 | } | ||
74 | EXPORT_SYMBOL(ps2_end_command); | ||
75 | |||
57 | /* | 76 | /* |
58 | * ps2_drain() waits for device to transmit requested number of bytes | 77 | * ps2_drain() waits for device to transmit requested number of bytes |
59 | * and discards them. | 78 | * and discards them. |
@@ -66,7 +85,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
66 | maxbytes = sizeof(ps2dev->cmdbuf); | 85 | maxbytes = sizeof(ps2dev->cmdbuf); |
67 | } | 86 | } |
68 | 87 | ||
69 | mutex_lock(&ps2dev->cmd_mutex); | 88 | ps2_begin_command(ps2dev); |
70 | 89 | ||
71 | serio_pause_rx(ps2dev->serio); | 90 | serio_pause_rx(ps2dev->serio); |
72 | ps2dev->flags = PS2_FLAG_CMD; | 91 | ps2dev->flags = PS2_FLAG_CMD; |
@@ -76,7 +95,8 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | |||
76 | wait_event_timeout(ps2dev->wait, | 95 | wait_event_timeout(ps2dev->wait, |
77 | !(ps2dev->flags & PS2_FLAG_CMD), | 96 | !(ps2dev->flags & PS2_FLAG_CMD), |
78 | msecs_to_jiffies(timeout)); | 97 | msecs_to_jiffies(timeout)); |
79 | mutex_unlock(&ps2dev->cmd_mutex); | 98 | |
99 | ps2_end_command(ps2dev); | ||
80 | } | 100 | } |
81 | EXPORT_SYMBOL(ps2_drain); | 101 | EXPORT_SYMBOL(ps2_drain); |
82 | 102 | ||
@@ -237,9 +257,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
237 | { | 257 | { |
238 | int rc; | 258 | int rc; |
239 | 259 | ||
240 | mutex_lock(&ps2dev->cmd_mutex); | 260 | ps2_begin_command(ps2dev); |
241 | rc = __ps2_command(ps2dev, param, command); | 261 | rc = __ps2_command(ps2dev, param, command); |
242 | mutex_unlock(&ps2dev->cmd_mutex); | 262 | ps2_end_command(ps2dev); |
243 | 263 | ||
244 | return rc; | 264 | return rc; |
245 | } | 265 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index ab02d72afbf3..8cc453c85ea7 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -48,8 +48,8 @@ config TOUCHSCREEN_AD7879_I2C | |||
48 | select TOUCHSCREEN_AD7879 | 48 | select TOUCHSCREEN_AD7879 |
49 | help | 49 | help |
50 | Say Y here if you have a touchscreen interface using the | 50 | Say Y here if you have a touchscreen interface using the |
51 | AD7879-1 controller, and your board-specific initialization | 51 | AD7879-1/AD7889-1 controller, and your board-specific |
52 | code includes that in its table of I2C devices. | 52 | initialization code includes that in its table of I2C devices. |
53 | 53 | ||
54 | If unsure, say N (but it's safe to say "Y"). | 54 | If unsure, say N (but it's safe to say "Y"). |
55 | 55 | ||
@@ -62,7 +62,7 @@ config TOUCHSCREEN_AD7879_SPI | |||
62 | select TOUCHSCREEN_AD7879 | 62 | select TOUCHSCREEN_AD7879 |
63 | help | 63 | help |
64 | Say Y here if you have a touchscreen interface using the | 64 | Say Y here if you have a touchscreen interface using the |
65 | AD7879 controller, and your board-specific initialization | 65 | AD7879/AD7889 controller, and your board-specific initialization |
66 | code includes that in its table of SPI devices. | 66 | code includes that in its table of SPI devices. |
67 | 67 | ||
68 | If unsure, say N (but it's safe to say "Y"). | 68 | If unsure, say N (but it's safe to say "Y"). |
@@ -169,6 +169,17 @@ config TOUCHSCREEN_WACOM_W8001 | |||
169 | To compile this driver as a module, choose M here: the | 169 | To compile this driver as a module, choose M here: the |
170 | module will be called wacom_w8001. | 170 | module will be called wacom_w8001. |
171 | 171 | ||
172 | config TOUCHSCREEN_MCS5000 | ||
173 | tristate "MELFAS MCS-5000 touchscreen" | ||
174 | depends on I2C | ||
175 | help | ||
176 | Say Y here if you have the MELFAS MCS-5000 touchscreen controller | ||
177 | chip in your system. | ||
178 | |||
179 | If unsure, say N. | ||
180 | |||
181 | To compile this driver as a module, choose M here: the | ||
182 | module will be called mcs5000_ts. | ||
172 | 183 | ||
173 | config TOUCHSCREEN_MTOUCH | 184 | config TOUCHSCREEN_MTOUCH |
174 | tristate "MicroTouch serial touchscreens" | 185 | tristate "MicroTouch serial touchscreens" |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4599bf7ad819..15fa62cffc77 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -17,6 +17,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | |||
17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
20 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o | ||
20 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o | 21 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o |
21 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 22 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
22 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o | 23 | obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 19b4db7e974d..f06332c9e21b 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2008 Michael Hennerich, Analog Devices Inc. | 2 | * Copyright (C) 2008-2009 Michael Hennerich, Analog Devices Inc. |
3 | * | 3 | * |
4 | * Description: AD7879 based touchscreen, and GPIO driver (I2C/SPI Interface) | 4 | * Description: AD7879/AD7889 based touchscreen, and GPIO driver |
5 | * (I2C/SPI Interface) | ||
5 | * | 6 | * |
6 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 7 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
7 | * | 8 | * |
@@ -747,6 +748,7 @@ static int __devexit ad7879_remove(struct i2c_client *client) | |||
747 | 748 | ||
748 | static const struct i2c_device_id ad7879_id[] = { | 749 | static const struct i2c_device_id ad7879_id[] = { |
749 | { "ad7879", 0 }, | 750 | { "ad7879", 0 }, |
751 | { "ad7889", 0 }, | ||
750 | { } | 752 | { } |
751 | }; | 753 | }; |
752 | MODULE_DEVICE_TABLE(i2c, ad7879_id); | 754 | MODULE_DEVICE_TABLE(i2c, ad7879_id); |
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c new file mode 100644 index 000000000000..4c28b89757f9 --- /dev/null +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
6 | * | ||
7 | * Based on wm97xx-core.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/i2c/mcs5000_ts.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | /* Registers */ | ||
25 | #define MCS5000_TS_STATUS 0x00 | ||
26 | #define STATUS_OFFSET 0 | ||
27 | #define STATUS_NO (0 << STATUS_OFFSET) | ||
28 | #define STATUS_INIT (1 << STATUS_OFFSET) | ||
29 | #define STATUS_SENSING (2 << STATUS_OFFSET) | ||
30 | #define STATUS_COORD (3 << STATUS_OFFSET) | ||
31 | #define STATUS_GESTURE (4 << STATUS_OFFSET) | ||
32 | #define ERROR_OFFSET 4 | ||
33 | #define ERROR_NO (0 << ERROR_OFFSET) | ||
34 | #define ERROR_POWER_ON_RESET (1 << ERROR_OFFSET) | ||
35 | #define ERROR_INT_RESET (2 << ERROR_OFFSET) | ||
36 | #define ERROR_EXT_RESET (3 << ERROR_OFFSET) | ||
37 | #define ERROR_INVALID_REG_ADDRESS (8 << ERROR_OFFSET) | ||
38 | #define ERROR_INVALID_REG_VALUE (9 << ERROR_OFFSET) | ||
39 | |||
40 | #define MCS5000_TS_OP_MODE 0x01 | ||
41 | #define RESET_OFFSET 0 | ||
42 | #define RESET_NO (0 << RESET_OFFSET) | ||
43 | #define RESET_EXT_SOFT (1 << RESET_OFFSET) | ||
44 | #define OP_MODE_OFFSET 1 | ||
45 | #define OP_MODE_SLEEP (0 << OP_MODE_OFFSET) | ||
46 | #define OP_MODE_ACTIVE (1 << OP_MODE_OFFSET) | ||
47 | #define GESTURE_OFFSET 4 | ||
48 | #define GESTURE_DISABLE (0 << GESTURE_OFFSET) | ||
49 | #define GESTURE_ENABLE (1 << GESTURE_OFFSET) | ||
50 | #define PROXIMITY_OFFSET 5 | ||
51 | #define PROXIMITY_DISABLE (0 << PROXIMITY_OFFSET) | ||
52 | #define PROXIMITY_ENABLE (1 << PROXIMITY_OFFSET) | ||
53 | #define SCAN_MODE_OFFSET 6 | ||
54 | #define SCAN_MODE_INTERRUPT (0 << SCAN_MODE_OFFSET) | ||
55 | #define SCAN_MODE_POLLING (1 << SCAN_MODE_OFFSET) | ||
56 | #define REPORT_RATE_OFFSET 7 | ||
57 | #define REPORT_RATE_40 (0 << REPORT_RATE_OFFSET) | ||
58 | #define REPORT_RATE_80 (1 << REPORT_RATE_OFFSET) | ||
59 | |||
60 | #define MCS5000_TS_SENS_CTL 0x02 | ||
61 | #define MCS5000_TS_FILTER_CTL 0x03 | ||
62 | #define PRI_FILTER_OFFSET 0 | ||
63 | #define SEC_FILTER_OFFSET 4 | ||
64 | |||
65 | #define MCS5000_TS_X_SIZE_UPPER 0x08 | ||
66 | #define MCS5000_TS_X_SIZE_LOWER 0x09 | ||
67 | #define MCS5000_TS_Y_SIZE_UPPER 0x0A | ||
68 | #define MCS5000_TS_Y_SIZE_LOWER 0x0B | ||
69 | |||
70 | #define MCS5000_TS_INPUT_INFO 0x10 | ||
71 | #define INPUT_TYPE_OFFSET 0 | ||
72 | #define INPUT_TYPE_NONTOUCH (0 << INPUT_TYPE_OFFSET) | ||
73 | #define INPUT_TYPE_SINGLE (1 << INPUT_TYPE_OFFSET) | ||
74 | #define INPUT_TYPE_DUAL (2 << INPUT_TYPE_OFFSET) | ||
75 | #define INPUT_TYPE_PALM (3 << INPUT_TYPE_OFFSET) | ||
76 | #define INPUT_TYPE_PROXIMITY (7 << INPUT_TYPE_OFFSET) | ||
77 | #define GESTURE_CODE_OFFSET 3 | ||
78 | #define GESTURE_CODE_NO (0 << GESTURE_CODE_OFFSET) | ||
79 | |||
80 | #define MCS5000_TS_X_POS_UPPER 0x11 | ||
81 | #define MCS5000_TS_X_POS_LOWER 0x12 | ||
82 | #define MCS5000_TS_Y_POS_UPPER 0x13 | ||
83 | #define MCS5000_TS_Y_POS_LOWER 0x14 | ||
84 | #define MCS5000_TS_Z_POS 0x15 | ||
85 | #define MCS5000_TS_WIDTH 0x16 | ||
86 | #define MCS5000_TS_GESTURE_VAL 0x17 | ||
87 | #define MCS5000_TS_MODULE_REV 0x20 | ||
88 | #define MCS5000_TS_FIRMWARE_VER 0x21 | ||
89 | |||
90 | /* Touchscreen absolute values */ | ||
91 | #define MCS5000_MAX_XC 0x3ff | ||
92 | #define MCS5000_MAX_YC 0x3ff | ||
93 | |||
94 | enum mcs5000_ts_read_offset { | ||
95 | READ_INPUT_INFO, | ||
96 | READ_X_POS_UPPER, | ||
97 | READ_X_POS_LOWER, | ||
98 | READ_Y_POS_UPPER, | ||
99 | READ_Y_POS_LOWER, | ||
100 | READ_BLOCK_SIZE, | ||
101 | }; | ||
102 | |||
103 | /* Each client has this additional data */ | ||
104 | struct mcs5000_ts_data { | ||
105 | struct i2c_client *client; | ||
106 | struct input_dev *input_dev; | ||
107 | const struct mcs5000_ts_platform_data *platform_data; | ||
108 | }; | ||
109 | |||
110 | static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id) | ||
111 | { | ||
112 | struct mcs5000_ts_data *data = dev_id; | ||
113 | struct i2c_client *client = data->client; | ||
114 | u8 buffer[READ_BLOCK_SIZE]; | ||
115 | int err; | ||
116 | int x; | ||
117 | int y; | ||
118 | |||
119 | err = i2c_smbus_read_i2c_block_data(client, MCS5000_TS_INPUT_INFO, | ||
120 | READ_BLOCK_SIZE, buffer); | ||
121 | if (err < 0) { | ||
122 | dev_err(&client->dev, "%s, err[%d]\n", __func__, err); | ||
123 | goto out; | ||
124 | } | ||
125 | |||
126 | switch (buffer[READ_INPUT_INFO]) { | ||
127 | case INPUT_TYPE_NONTOUCH: | ||
128 | input_report_key(data->input_dev, BTN_TOUCH, 0); | ||
129 | input_sync(data->input_dev); | ||
130 | break; | ||
131 | |||
132 | case INPUT_TYPE_SINGLE: | ||
133 | x = (buffer[READ_X_POS_UPPER] << 8) | buffer[READ_X_POS_LOWER]; | ||
134 | y = (buffer[READ_Y_POS_UPPER] << 8) | buffer[READ_Y_POS_LOWER]; | ||
135 | |||
136 | input_report_key(data->input_dev, BTN_TOUCH, 1); | ||
137 | input_report_abs(data->input_dev, ABS_X, x); | ||
138 | input_report_abs(data->input_dev, ABS_Y, y); | ||
139 | input_sync(data->input_dev); | ||
140 | break; | ||
141 | |||
142 | case INPUT_TYPE_DUAL: | ||
143 | /* TODO */ | ||
144 | break; | ||
145 | |||
146 | case INPUT_TYPE_PALM: | ||
147 | /* TODO */ | ||
148 | break; | ||
149 | |||
150 | case INPUT_TYPE_PROXIMITY: | ||
151 | /* TODO */ | ||
152 | break; | ||
153 | |||
154 | default: | ||
155 | dev_err(&client->dev, "Unknown ts input type %d\n", | ||
156 | buffer[READ_INPUT_INFO]); | ||
157 | break; | ||
158 | } | ||
159 | |||
160 | out: | ||
161 | return IRQ_HANDLED; | ||
162 | } | ||
163 | |||
164 | static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) | ||
165 | { | ||
166 | const struct mcs5000_ts_platform_data *platform_data = | ||
167 | data->platform_data; | ||
168 | struct i2c_client *client = data->client; | ||
169 | |||
170 | /* Touch reset & sleep mode */ | ||
171 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, | ||
172 | RESET_EXT_SOFT | OP_MODE_SLEEP); | ||
173 | |||
174 | /* Touch size */ | ||
175 | i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_UPPER, | ||
176 | platform_data->x_size >> 8); | ||
177 | i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_LOWER, | ||
178 | platform_data->x_size & 0xff); | ||
179 | i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_UPPER, | ||
180 | platform_data->y_size >> 8); | ||
181 | i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_LOWER, | ||
182 | platform_data->y_size & 0xff); | ||
183 | |||
184 | /* Touch active mode & 80 report rate */ | ||
185 | i2c_smbus_write_byte_data(data->client, MCS5000_TS_OP_MODE, | ||
186 | OP_MODE_ACTIVE | REPORT_RATE_80); | ||
187 | } | ||
188 | |||
189 | static int __devinit mcs5000_ts_probe(struct i2c_client *client, | ||
190 | const struct i2c_device_id *id) | ||
191 | { | ||
192 | struct mcs5000_ts_data *data; | ||
193 | struct input_dev *input_dev; | ||
194 | int ret; | ||
195 | |||
196 | if (!client->dev.platform_data) | ||
197 | return -EINVAL; | ||
198 | |||
199 | data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL); | ||
200 | input_dev = input_allocate_device(); | ||
201 | if (!data || !input_dev) { | ||
202 | dev_err(&client->dev, "Failed to allocate memory\n"); | ||
203 | ret = -ENOMEM; | ||
204 | goto err_free_mem; | ||
205 | } | ||
206 | |||
207 | data->client = client; | ||
208 | data->input_dev = input_dev; | ||
209 | data->platform_data = client->dev.platform_data; | ||
210 | |||
211 | input_dev->name = "MELPAS MCS-5000 Touchscreen"; | ||
212 | input_dev->id.bustype = BUS_I2C; | ||
213 | input_dev->dev.parent = &client->dev; | ||
214 | |||
215 | __set_bit(EV_ABS, input_dev->evbit); | ||
216 | __set_bit(EV_KEY, input_dev->evbit); | ||
217 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
218 | input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0); | ||
219 | input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0); | ||
220 | |||
221 | input_set_drvdata(input_dev, data); | ||
222 | |||
223 | if (data->platform_data->cfg_pin) | ||
224 | data->platform_data->cfg_pin(); | ||
225 | |||
226 | ret = request_threaded_irq(client->irq, NULL, mcs5000_ts_interrupt, | ||
227 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mcs5000_ts", data); | ||
228 | |||
229 | if (ret < 0) { | ||
230 | dev_err(&client->dev, "Failed to register interrupt\n"); | ||
231 | goto err_free_mem; | ||
232 | } | ||
233 | |||
234 | ret = input_register_device(data->input_dev); | ||
235 | if (ret < 0) | ||
236 | goto err_free_irq; | ||
237 | |||
238 | mcs5000_ts_phys_init(data); | ||
239 | i2c_set_clientdata(client, data); | ||
240 | |||
241 | return 0; | ||
242 | |||
243 | err_free_irq: | ||
244 | free_irq(client->irq, data); | ||
245 | err_free_mem: | ||
246 | input_free_device(input_dev); | ||
247 | kfree(data); | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static int __devexit mcs5000_ts_remove(struct i2c_client *client) | ||
252 | { | ||
253 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | ||
254 | |||
255 | free_irq(client->irq, data); | ||
256 | input_unregister_device(data->input_dev); | ||
257 | kfree(data); | ||
258 | i2c_set_clientdata(client, NULL); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | #ifdef CONFIG_PM | ||
264 | static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg) | ||
265 | { | ||
266 | /* Touch sleep mode */ | ||
267 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int mcs5000_ts_resume(struct i2c_client *client) | ||
273 | { | ||
274 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | ||
275 | |||
276 | mcs5000_ts_phys_init(data); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | #else | ||
281 | #define mcs5000_ts_suspend NULL | ||
282 | #define mcs5000_ts_resume NULL | ||
283 | #endif | ||
284 | |||
285 | static const struct i2c_device_id mcs5000_ts_id[] = { | ||
286 | { "mcs5000_ts", 0 }, | ||
287 | { } | ||
288 | }; | ||
289 | MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); | ||
290 | |||
291 | static struct i2c_driver mcs5000_ts_driver = { | ||
292 | .probe = mcs5000_ts_probe, | ||
293 | .remove = __devexit_p(mcs5000_ts_remove), | ||
294 | .suspend = mcs5000_ts_suspend, | ||
295 | .resume = mcs5000_ts_resume, | ||
296 | .driver = { | ||
297 | .name = "mcs5000_ts", | ||
298 | }, | ||
299 | .id_table = mcs5000_ts_id, | ||
300 | }; | ||
301 | |||
302 | static int __init mcs5000_ts_init(void) | ||
303 | { | ||
304 | return i2c_add_driver(&mcs5000_ts_driver); | ||
305 | } | ||
306 | |||
307 | static void __exit mcs5000_ts_exit(void) | ||
308 | { | ||
309 | i2c_del_driver(&mcs5000_ts_driver); | ||
310 | } | ||
311 | |||
312 | module_init(mcs5000_ts_init); | ||
313 | module_exit(mcs5000_ts_exit); | ||
314 | |||
315 | /* Module information */ | ||
316 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
317 | MODULE_DESCRIPTION("Touchscreen driver for MELFAS MCS-5000 controller"); | ||
318 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c index 1813c84ea5fc..f2242db54016 100644 --- a/drivers/leds/leds-clevo-mail.c +++ b/drivers/leds/leds-clevo-mail.c | |||
@@ -93,6 +93,8 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = { | |||
93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, | 93 | static void clevo_mail_led_set(struct led_classdev *led_cdev, |
94 | enum led_brightness value) | 94 | enum led_brightness value) |
95 | { | 95 | { |
96 | i8042_lock_chip(); | ||
97 | |||
96 | if (value == LED_OFF) | 98 | if (value == LED_OFF) |
97 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); | 99 | i8042_command(NULL, CLEVO_MAIL_LED_OFF); |
98 | else if (value <= LED_HALF) | 100 | else if (value <= LED_HALF) |
@@ -100,6 +102,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev, | |||
100 | else | 102 | else |
101 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); | 103 | i8042_command(NULL, CLEVO_MAIL_LED_BLINK_1HZ); |
102 | 104 | ||
105 | i8042_unlock_chip(); | ||
106 | |||
103 | } | 107 | } |
104 | 108 | ||
105 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, | 109 | static int clevo_mail_led_blink(struct led_classdev *led_cdev, |
@@ -108,6 +112,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
108 | { | 112 | { |
109 | int status = -EINVAL; | 113 | int status = -EINVAL; |
110 | 114 | ||
115 | i8042_lock_chip(); | ||
116 | |||
111 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { | 117 | if (*delay_on == 0 /* ms */ && *delay_off == 0 /* ms */) { |
112 | /* Special case: the leds subsystem requested us to | 118 | /* Special case: the leds subsystem requested us to |
113 | * chose one user friendly blinking of the LED, and | 119 | * chose one user friendly blinking of the LED, and |
@@ -135,6 +141,8 @@ static int clevo_mail_led_blink(struct led_classdev *led_cdev, | |||
135 | *delay_on, *delay_off); | 141 | *delay_on, *delay_off); |
136 | } | 142 | } |
137 | 143 | ||
144 | i8042_unlock_chip(); | ||
145 | |||
138 | return status; | 146 | return status; |
139 | } | 147 | } |
140 | 148 | ||
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index fb45f5ee8df1..454970d2d701 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -746,7 +746,9 @@ static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) | |||
746 | return AE_BAD_PARAMETER; | 746 | return AE_BAD_PARAMETER; |
747 | if (quirks->mailled == 1) { | 747 | if (quirks->mailled == 1) { |
748 | param = value ? 0x92 : 0x93; | 748 | param = value ? 0x92 : 0x93; |
749 | i8042_lock_chip(); | ||
749 | i8042_command(¶m, 0x1059); | 750 | i8042_command(¶m, 0x1059); |
751 | i8042_unlock_chip(); | ||
750 | return 0; | 752 | return 0; |
751 | } | 753 | } |
752 | break; | 754 | break; |