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 | |
| 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
24 files changed, 1987 insertions, 80 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; |
diff --git a/include/linux/i2c/adp5588.h b/include/linux/i2c/adp5588.h new file mode 100644 index 000000000000..fc5db826b48e --- /dev/null +++ b/include/linux/i2c/adp5588.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | /* | ||
| 2 | * Analog Devices ADP5588 I/O Expander and QWERTY Keypad Controller | ||
| 3 | * | ||
| 4 | * Copyright 2009 Analog Devices Inc. | ||
| 5 | * | ||
| 6 | * Licensed under the GPL-2 or later. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _ADP5588_H | ||
| 10 | #define _ADP5588_H | ||
| 11 | |||
| 12 | #define DEV_ID 0x00 /* Device ID */ | ||
| 13 | #define CFG 0x01 /* Configuration Register1 */ | ||
| 14 | #define INT_STAT 0x02 /* Interrupt Status Register */ | ||
| 15 | #define KEY_LCK_EC_STAT 0x03 /* Key Lock and Event Counter Register */ | ||
| 16 | #define Key_EVENTA 0x04 /* Key Event Register A */ | ||
| 17 | #define Key_EVENTB 0x05 /* Key Event Register B */ | ||
| 18 | #define Key_EVENTC 0x06 /* Key Event Register C */ | ||
| 19 | #define Key_EVENTD 0x07 /* Key Event Register D */ | ||
| 20 | #define Key_EVENTE 0x08 /* Key Event Register E */ | ||
| 21 | #define Key_EVENTF 0x09 /* Key Event Register F */ | ||
| 22 | #define Key_EVENTG 0x0A /* Key Event Register G */ | ||
| 23 | #define Key_EVENTH 0x0B /* Key Event Register H */ | ||
| 24 | #define Key_EVENTI 0x0C /* Key Event Register I */ | ||
| 25 | #define Key_EVENTJ 0x0D /* Key Event Register J */ | ||
| 26 | #define KP_LCK_TMR 0x0E /* Keypad Lock1 to Lock2 Timer */ | ||
| 27 | #define UNLOCK1 0x0F /* Unlock Key1 */ | ||
| 28 | #define UNLOCK2 0x10 /* Unlock Key2 */ | ||
| 29 | #define GPIO_INT_STAT1 0x11 /* GPIO Interrupt Status */ | ||
| 30 | #define GPIO_INT_STAT2 0x12 /* GPIO Interrupt Status */ | ||
| 31 | #define GPIO_INT_STAT3 0x13 /* GPIO Interrupt Status */ | ||
| 32 | #define GPIO_DAT_STAT1 0x14 /* GPIO Data Status, Read twice to clear */ | ||
| 33 | #define GPIO_DAT_STAT2 0x15 /* GPIO Data Status, Read twice to clear */ | ||
| 34 | #define GPIO_DAT_STAT3 0x16 /* GPIO Data Status, Read twice to clear */ | ||
| 35 | #define GPIO_DAT_OUT1 0x17 /* GPIO DATA OUT */ | ||
| 36 | #define GPIO_DAT_OUT2 0x18 /* GPIO DATA OUT */ | ||
| 37 | #define GPIO_DAT_OUT3 0x19 /* GPIO DATA OUT */ | ||
| 38 | #define GPIO_INT_EN1 0x1A /* GPIO Interrupt Enable */ | ||
| 39 | #define GPIO_INT_EN2 0x1B /* GPIO Interrupt Enable */ | ||
| 40 | #define GPIO_INT_EN3 0x1C /* GPIO Interrupt Enable */ | ||
| 41 | #define KP_GPIO1 0x1D /* Keypad or GPIO Selection */ | ||
| 42 | #define KP_GPIO2 0x1E /* Keypad or GPIO Selection */ | ||
| 43 | #define KP_GPIO3 0x1F /* Keypad or GPIO Selection */ | ||
| 44 | #define GPI_EM1 0x20 /* GPI Event Mode 1 */ | ||
| 45 | #define GPI_EM2 0x21 /* GPI Event Mode 2 */ | ||
| 46 | #define GPI_EM3 0x22 /* GPI Event Mode 3 */ | ||
| 47 | #define GPIO_DIR1 0x23 /* GPIO Data Direction */ | ||
| 48 | #define GPIO_DIR2 0x24 /* GPIO Data Direction */ | ||
| 49 | #define GPIO_DIR3 0x25 /* GPIO Data Direction */ | ||
| 50 | #define GPIO_INT_LVL1 0x26 /* GPIO Edge/Level Detect */ | ||
| 51 | #define GPIO_INT_LVL2 0x27 /* GPIO Edge/Level Detect */ | ||
| 52 | #define GPIO_INT_LVL3 0x28 /* GPIO Edge/Level Detect */ | ||
| 53 | #define Debounce_DIS1 0x29 /* Debounce Disable */ | ||
| 54 | #define Debounce_DIS2 0x2A /* Debounce Disable */ | ||
| 55 | #define Debounce_DIS3 0x2B /* Debounce Disable */ | ||
| 56 | #define GPIO_PULL1 0x2C /* GPIO Pull Disable */ | ||
| 57 | #define GPIO_PULL2 0x2D /* GPIO Pull Disable */ | ||
| 58 | #define GPIO_PULL3 0x2E /* GPIO Pull Disable */ | ||
| 59 | #define CMP_CFG_STAT 0x30 /* Comparator Configuration and Status Register */ | ||
| 60 | #define CMP_CONFG_SENS1 0x31 /* Sensor1 Comparator Configuration Register */ | ||
| 61 | #define CMP_CONFG_SENS2 0x32 /* L2 Light Sensor Reference Level, Output Falling for Sensor 1 */ | ||
| 62 | #define CMP1_LVL2_TRIP 0x33 /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 1 */ | ||
| 63 | #define CMP1_LVL2_HYS 0x34 /* L3 Light Sensor Reference Level, Output Falling For Sensor 1 */ | ||
| 64 | #define CMP1_LVL3_TRIP 0x35 /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 1 */ | ||
| 65 | #define CMP1_LVL3_HYS 0x36 /* Sensor 2 Comparator Configuration Register */ | ||
| 66 | #define CMP2_LVL2_TRIP 0x37 /* L2 Light Sensor Reference Level, Output Falling for Sensor 2 */ | ||
| 67 | #define CMP2_LVL2_HYS 0x38 /* L2 Light Sensor Hysteresis (Active when Output Rising) for Sensor 2 */ | ||
| 68 | #define CMP2_LVL3_TRIP 0x39 /* L3 Light Sensor Reference Level, Output Falling For Sensor 2 */ | ||
| 69 | #define CMP2_LVL3_HYS 0x3A /* L3 Light Sensor Hysteresis (Active when Output Rising) For Sensor 2 */ | ||
| 70 | #define CMP1_ADC_DAT_R1 0x3B /* Comparator 1 ADC data Register1 */ | ||
| 71 | #define CMP1_ADC_DAT_R2 0x3C /* Comparator 1 ADC data Register2 */ | ||
| 72 | #define CMP2_ADC_DAT_R1 0x3D /* Comparator 2 ADC data Register1 */ | ||
| 73 | #define CMP2_ADC_DAT_R2 0x3E /* Comparator 2 ADC data Register2 */ | ||
| 74 | |||
| 75 | #define ADP5588_DEVICE_ID_MASK 0xF | ||
| 76 | |||
| 77 | /* Put one of these structures in i2c_board_info platform_data */ | ||
| 78 | |||
| 79 | #define ADP5588_KEYMAPSIZE 80 | ||
| 80 | |||
| 81 | struct adp5588_kpad_platform_data { | ||
| 82 | int rows; /* Number of rows */ | ||
| 83 | int cols; /* Number of columns */ | ||
| 84 | const unsigned short *keymap; /* Pointer to keymap */ | ||
| 85 | unsigned short keymapsize; /* Keymap size */ | ||
| 86 | unsigned repeat:1; /* Enable key repeat */ | ||
| 87 | unsigned en_keylock:1; /* Enable Key Lock feature */ | ||
| 88 | unsigned short unlock_key1; /* Unlock Key 1 */ | ||
| 89 | unsigned short unlock_key2; /* Unlock Key 2 */ | ||
| 90 | }; | ||
| 91 | |||
| 92 | #endif | ||
diff --git a/include/linux/i2c/mcs5000_ts.h b/include/linux/i2c/mcs5000_ts.h new file mode 100644 index 000000000000..5a117b5ca15e --- /dev/null +++ b/include/linux/i2c/mcs5000_ts.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | /* | ||
| 2 | * mcs5000_ts.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Samsung Electronics Co.Ltd | ||
| 5 | * Author: Joonyoung Shim <jy0922.shim@samsung.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef __LINUX_MCS5000_TS_H | ||
| 15 | #define __LINUX_MCS5000_TS_H | ||
| 16 | |||
| 17 | /* platform data for the MELFAS MCS-5000 touchscreen driver */ | ||
| 18 | struct mcs5000_ts_platform_data { | ||
| 19 | void (*cfg_pin)(void); | ||
| 20 | int x_size; | ||
| 21 | int y_size; | ||
| 22 | }; | ||
| 23 | |||
| 24 | #endif /* __LINUX_MCS5000_TS_H */ | ||
diff --git a/include/linux/i8042.h b/include/linux/i8042.h index 7907a72403ee..60c3360ef6ad 100644 --- a/include/linux/i8042.h +++ b/include/linux/i8042.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/types.h> | ||
| 10 | 11 | ||
| 11 | /* | 12 | /* |
| 12 | * Standard commands. | 13 | * Standard commands. |
| @@ -30,6 +31,35 @@ | |||
| 30 | #define I8042_CMD_MUX_PFX 0x0090 | 31 | #define I8042_CMD_MUX_PFX 0x0090 |
| 31 | #define I8042_CMD_MUX_SEND 0x1090 | 32 | #define I8042_CMD_MUX_SEND 0x1090 |
| 32 | 33 | ||
| 34 | struct serio; | ||
| 35 | |||
| 36 | #if defined(CONFIG_SERIO_I8042) || defined(CONFIG_SERIO_I8042_MODULE) | ||
| 37 | |||
| 38 | void i8042_lock_chip(void); | ||
| 39 | void i8042_unlock_chip(void); | ||
| 33 | int i8042_command(unsigned char *param, int command); | 40 | int i8042_command(unsigned char *param, int command); |
| 41 | bool i8042_check_port_owner(const struct serio *); | ||
| 42 | |||
| 43 | #else | ||
| 44 | |||
| 45 | void i8042_lock_chip(void) | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | void i8042_unlock_chip(void) | ||
| 50 | { | ||
| 51 | } | ||
| 52 | |||
| 53 | int i8042_command(unsigned char *param, int command) | ||
| 54 | { | ||
| 55 | return -ENOSYS; | ||
| 56 | } | ||
| 57 | |||
| 58 | bool i8042_check_port_owner(const struct serio *serio) | ||
| 59 | { | ||
| 60 | return false; | ||
| 61 | } | ||
| 62 | |||
| 63 | #endif | ||
| 34 | 64 | ||
| 35 | #endif | 65 | #endif |
diff --git a/include/linux/input.h b/include/linux/input.h index 8b3bc3e0d146..0ccfc30cd40f 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -1123,7 +1123,7 @@ struct input_dev { | |||
| 1123 | struct mutex mutex; | 1123 | struct mutex mutex; |
| 1124 | 1124 | ||
| 1125 | unsigned int users; | 1125 | unsigned int users; |
| 1126 | int going_away; | 1126 | bool going_away; |
| 1127 | 1127 | ||
| 1128 | struct device dev; | 1128 | struct device dev; |
| 1129 | 1129 | ||
diff --git a/include/linux/libps2.h b/include/linux/libps2.h index fcf5fbe6a50c..79603a6c356f 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h | |||
| @@ -44,6 +44,8 @@ struct ps2dev { | |||
| 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); | 44 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); |
| 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); | 45 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); |
| 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); | 46 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); |
| 47 | void ps2_begin_command(struct ps2dev *ps2dev); | ||
| 48 | void ps2_end_command(struct ps2dev *ps2dev); | ||
| 47 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 49 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 48 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 50 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 49 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); | 51 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); |
