diff options
Diffstat (limited to 'drivers/input')
63 files changed, 3736 insertions, 1548 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9a1d55b74d7a..901b2525993e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
453 | } | 453 | } |
454 | 454 | ||
455 | static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, | ||
456 | void __user *argp, size_t len) | ||
457 | { | ||
458 | __u8 *abspam; | ||
459 | int i; | ||
460 | int retval = 0; | ||
461 | |||
462 | len = min(len, sizeof(joydev->abspam)); | ||
463 | |||
464 | /* Validate the map. */ | ||
465 | abspam = kmalloc(len, GFP_KERNEL); | ||
466 | if (!abspam) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | if (copy_from_user(abspam, argp, len)) { | ||
470 | retval = -EFAULT; | ||
471 | goto out; | ||
472 | } | ||
473 | |||
474 | for (i = 0; i < joydev->nabs; i++) { | ||
475 | if (abspam[i] > ABS_MAX) { | ||
476 | retval = -EINVAL; | ||
477 | goto out; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | memcpy(joydev->abspam, abspam, len); | ||
482 | |||
483 | out: | ||
484 | kfree(abspam); | ||
485 | return retval; | ||
486 | } | ||
487 | |||
488 | static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, | ||
489 | void __user *argp, size_t len) | ||
490 | { | ||
491 | __u16 *keypam; | ||
492 | int i; | ||
493 | int retval = 0; | ||
494 | |||
495 | len = min(len, sizeof(joydev->keypam)); | ||
496 | |||
497 | /* Validate the map. */ | ||
498 | keypam = kmalloc(len, GFP_KERNEL); | ||
499 | if (!keypam) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | if (copy_from_user(keypam, argp, len)) { | ||
503 | retval = -EFAULT; | ||
504 | goto out; | ||
505 | } | ||
506 | |||
507 | for (i = 0; i < joydev->nkey; i++) { | ||
508 | if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { | ||
509 | retval = -EINVAL; | ||
510 | goto out; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | memcpy(joydev->keypam, keypam, len); | ||
515 | |||
516 | for (i = 0; i < joydev->nkey; i++) | ||
517 | joydev->keymap[keypam[i] - BTN_MISC] = i; | ||
518 | |||
519 | out: | ||
520 | kfree(keypam); | ||
521 | return retval; | ||
522 | } | ||
523 | |||
524 | |||
455 | static int joydev_ioctl_common(struct joydev *joydev, | 525 | static int joydev_ioctl_common(struct joydev *joydev, |
456 | unsigned int cmd, void __user *argp) | 526 | unsigned int cmd, void __user *argp) |
457 | { | 527 | { |
@@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
512 | switch (cmd & ~IOCSIZE_MASK) { | 582 | switch (cmd & ~IOCSIZE_MASK) { |
513 | 583 | ||
514 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): | 584 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): |
515 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 585 | return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd)); |
516 | /* | ||
517 | * FIXME: we should not copy into our axis map before | ||
518 | * validating the data. | ||
519 | */ | ||
520 | if (copy_from_user(joydev->abspam, argp, len)) | ||
521 | return -EFAULT; | ||
522 | |||
523 | for (i = 0; i < joydev->nabs; i++) { | ||
524 | if (joydev->abspam[i] > ABS_MAX) | ||
525 | return -EINVAL; | ||
526 | joydev->absmap[joydev->abspam[i]] = i; | ||
527 | } | ||
528 | return 0; | ||
529 | 586 | ||
530 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): | 587 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): |
531 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 588 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); |
532 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; | 589 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len; |
533 | 590 | ||
534 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): | 591 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): |
535 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 592 | return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd)); |
536 | /* | ||
537 | * FIXME: we should not copy into our keymap before | ||
538 | * validating the data. | ||
539 | */ | ||
540 | if (copy_from_user(joydev->keypam, argp, len)) | ||
541 | return -EFAULT; | ||
542 | |||
543 | for (i = 0; i < joydev->nkey; i++) { | ||
544 | if (joydev->keypam[i] > KEY_MAX || | ||
545 | joydev->keypam[i] < BTN_MISC) | ||
546 | return -EINVAL; | ||
547 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
548 | } | ||
549 | |||
550 | return 0; | ||
551 | 593 | ||
552 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): | 594 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): |
553 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 595 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); |
554 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; | 596 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len; |
555 | 597 | ||
556 | case JSIOCGNAME(0): | 598 | case JSIOCGNAME(0): |
557 | name = dev->name; | 599 | name = dev->name; |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f155ad8cdae7..2388cf578a62 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -144,6 +144,7 @@ static const struct xpad_device { | |||
144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
147 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | ||
147 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 148 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
148 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } | 149 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } |
149 | }; | 150 | }; |
@@ -208,6 +209,7 @@ static struct usb_device_id xpad_table [] = { | |||
208 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | 209 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ |
209 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ | 210 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ |
210 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 211 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
212 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ | ||
211 | { } | 213 | { } |
212 | }; | 214 | }; |
213 | 215 | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a6b989a9dc07..3525c19be428 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -187,7 +187,7 @@ config KEYBOARD_HIL_OLD | |||
187 | submenu. | 187 | submenu. |
188 | 188 | ||
189 | config KEYBOARD_HIL | 189 | config KEYBOARD_HIL |
190 | tristate "HP HIL keyboard support" | 190 | tristate "HP HIL keyboard/pointer support" |
191 | depends on GSC || HP300 | 191 | depends on GSC || HP300 |
192 | default y | 192 | default y |
193 | select HP_SDC | 193 | select HP_SDC |
@@ -196,7 +196,8 @@ config KEYBOARD_HIL | |||
196 | help | 196 | help |
197 | The "Human Interface Loop" is a older, 8-channel USB-like | 197 | The "Human Interface Loop" is a older, 8-channel USB-like |
198 | controller used in several Hewlett Packard models. | 198 | controller used in several Hewlett Packard models. |
199 | This driver implements support for HIL-keyboards attached | 199 | This driver implements support for HIL-keyboards and pointing |
200 | devices (mice, tablets, touchscreens) attached | ||
200 | to your machine, so normally you should say Y here. | 201 | to your machine, so normally you should say Y here. |
201 | 202 | ||
202 | config KEYBOARD_HP6XX | 203 | config KEYBOARD_HP6XX |
@@ -329,6 +330,17 @@ config KEYBOARD_OMAP | |||
329 | To compile this driver as a module, choose M here: the | 330 | To compile this driver as a module, choose M here: the |
330 | module will be called omap-keypad. | 331 | module will be called omap-keypad. |
331 | 332 | ||
333 | config KEYBOARD_TWL4030 | ||
334 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | ||
335 | depends on TWL4030_CORE | ||
336 | help | ||
337 | Say Y here if your board use the keypad controller on | ||
338 | TWL4030 family chips. It's safe to say enable this | ||
339 | even on boards that don't use the keypad controller. | ||
340 | |||
341 | To compile this driver as a module, choose M here: the | ||
342 | module will be called twl4030_keypad. | ||
343 | |||
332 | config KEYBOARD_TOSA | 344 | config KEYBOARD_TOSA |
333 | tristate "Tosa keyboard" | 345 | tristate "Tosa keyboard" |
334 | depends on MACH_TOSA | 346 | depends on MACH_TOSA |
@@ -361,4 +373,14 @@ config KEYBOARD_XTKBD | |||
361 | To compile this driver as a module, choose M here: the | 373 | To compile this driver as a module, choose M here: the |
362 | module will be called xtkbd. | 374 | module will be called xtkbd. |
363 | 375 | ||
376 | config KEYBOARD_W90P910 | ||
377 | tristate "W90P910 Matrix Keypad support" | ||
378 | depends on ARCH_W90X900 | ||
379 | help | ||
380 | Say Y here to enable the matrix keypad on evaluation board | ||
381 | based on W90P910. | ||
382 | |||
383 | To compile this driver as a module, choose M here: the | ||
384 | module will be called w90p910_keypad. | ||
385 | |||
364 | endif | 386 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b5b5eae9724f..8a7a22b30266 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -30,4 +30,6 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | |||
30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o |
33 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | ||
33 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 34 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
35 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 6c6a09b1c0fe..c9523e48c6ad 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -68,7 +68,9 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and | |||
68 | * are loadable via a userland utility. | 68 | * are loadable via a userland utility. |
69 | */ | 69 | */ |
70 | 70 | ||
71 | static const unsigned short atkbd_set2_keycode[512] = { | 71 | #define ATKBD_KEYMAP_SIZE 512 |
72 | |||
73 | static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { | ||
72 | 74 | ||
73 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES | 75 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES |
74 | 76 | ||
@@ -99,7 +101,7 @@ static const unsigned short atkbd_set2_keycode[512] = { | |||
99 | #endif | 101 | #endif |
100 | }; | 102 | }; |
101 | 103 | ||
102 | static const unsigned short atkbd_set3_keycode[512] = { | 104 | static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = { |
103 | 105 | ||
104 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, | 106 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, |
105 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, | 107 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, |
@@ -200,8 +202,8 @@ struct atkbd { | |||
200 | char phys[32]; | 202 | char phys[32]; |
201 | 203 | ||
202 | unsigned short id; | 204 | unsigned short id; |
203 | unsigned short keycode[512]; | 205 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; |
204 | DECLARE_BITMAP(force_release_mask, 512); | 206 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); |
205 | unsigned char set; | 207 | unsigned char set; |
206 | unsigned char translated; | 208 | unsigned char translated; |
207 | unsigned char extra; | 209 | unsigned char extra; |
@@ -253,6 +255,7 @@ static struct device_attribute atkbd_attr_##_name = \ | |||
253 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 255 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
254 | 256 | ||
255 | ATKBD_DEFINE_ATTR(extra); | 257 | ATKBD_DEFINE_ATTR(extra); |
258 | ATKBD_DEFINE_ATTR(force_release); | ||
256 | ATKBD_DEFINE_ATTR(scroll); | 259 | ATKBD_DEFINE_ATTR(scroll); |
257 | ATKBD_DEFINE_ATTR(set); | 260 | ATKBD_DEFINE_ATTR(set); |
258 | ATKBD_DEFINE_ATTR(softrepeat); | 261 | ATKBD_DEFINE_ATTR(softrepeat); |
@@ -272,6 +275,7 @@ ATKBD_DEFINE_RO_ATTR(err_count); | |||
272 | 275 | ||
273 | static struct attribute *atkbd_attributes[] = { | 276 | static struct attribute *atkbd_attributes[] = { |
274 | &atkbd_attr_extra.attr, | 277 | &atkbd_attr_extra.attr, |
278 | &atkbd_attr_force_release.attr, | ||
275 | &atkbd_attr_scroll.attr, | 279 | &atkbd_attr_scroll.attr, |
276 | &atkbd_attr_set.attr, | 280 | &atkbd_attr_set.attr, |
277 | &atkbd_attr_softrepeat.attr, | 281 | &atkbd_attr_softrepeat.attr, |
@@ -934,7 +938,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
934 | int i, j; | 938 | int i, j; |
935 | 939 | ||
936 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); | 940 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
937 | bitmap_zero(atkbd->force_release_mask, 512); | 941 | bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); |
938 | 942 | ||
939 | if (atkbd->translated) { | 943 | if (atkbd->translated) { |
940 | for (i = 0; i < 128; i++) { | 944 | for (i = 0; i < 128; i++) { |
@@ -1041,7 +1045,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) | |||
1041 | input_dev->keycodesize = sizeof(unsigned short); | 1045 | input_dev->keycodesize = sizeof(unsigned short); |
1042 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); | 1046 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
1043 | 1047 | ||
1044 | for (i = 0; i < 512; i++) | 1048 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) |
1045 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) | 1049 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) |
1046 | __set_bit(atkbd->keycode[i], input_dev->keybit); | 1050 | __set_bit(atkbd->keycode[i], input_dev->keybit); |
1047 | } | 1051 | } |
@@ -1309,6 +1313,33 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1309 | return count; | 1313 | return count; |
1310 | } | 1314 | } |
1311 | 1315 | ||
1316 | static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf) | ||
1317 | { | ||
1318 | size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, | ||
1319 | atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); | ||
1320 | |||
1321 | buf[len++] = '\n'; | ||
1322 | buf[len] = '\0'; | ||
1323 | |||
1324 | return len; | ||
1325 | } | ||
1326 | |||
1327 | static ssize_t atkbd_set_force_release(struct atkbd *atkbd, | ||
1328 | const char *buf, size_t count) | ||
1329 | { | ||
1330 | /* 64 bytes on stack should be acceptable */ | ||
1331 | DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE); | ||
1332 | int err; | ||
1333 | |||
1334 | err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE); | ||
1335 | if (err) | ||
1336 | return err; | ||
1337 | |||
1338 | memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask)); | ||
1339 | return count; | ||
1340 | } | ||
1341 | |||
1342 | |||
1312 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) | 1343 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) |
1313 | { | 1344 | { |
1314 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); | 1345 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index d427f322e207..fe376a27fe57 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -184,14 +184,13 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
184 | int i, error; | 184 | int i, error; |
185 | 185 | ||
186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | 186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { |
187 | printk(KERN_ERR DRV_NAME | 187 | dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); |
188 | ": No rows, cols or keymap from pdata\n"); | ||
189 | return -EINVAL; | 188 | return -EINVAL; |
190 | } | 189 | } |
191 | 190 | ||
192 | if (!pdata->keymapsize || | 191 | if (!pdata->keymapsize || |
193 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | 192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { |
194 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | 193 | dev_err(&pdev->dev, "invalid keymapsize\n"); |
195 | return -EINVAL; | 194 | return -EINVAL; |
196 | } | 195 | } |
197 | 196 | ||
@@ -211,8 +210,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
211 | 210 | ||
212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 211 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 212 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
214 | printk(KERN_WARNING DRV_NAME | 213 | dev_warn(&pdev->dev, |
215 | ": Invalid Debounce/Columndrive Time in platform data\n"); | 214 | "invalid platform debounce/columndrive time\n"); |
216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
217 | } else { | 216 | } else { |
218 | bfin_write_KPAD_MSEL( | 217 | bfin_write_KPAD_MSEL( |
@@ -231,16 +230,14 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
231 | 230 | ||
232 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | 231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], |
233 | DRV_NAME)) { | 232 | DRV_NAME)) { |
234 | printk(KERN_ERR DRV_NAME | 233 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
235 | ": Requesting Peripherals failed\n"); | ||
236 | error = -EFAULT; | 234 | error = -EFAULT; |
237 | goto out0; | 235 | goto out0; |
238 | } | 236 | } |
239 | 237 | ||
240 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | 238 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], |
241 | DRV_NAME)) { | 239 | DRV_NAME)) { |
242 | printk(KERN_ERR DRV_NAME | 240 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
243 | ": Requesting Peripherals failed\n"); | ||
244 | error = -EFAULT; | 241 | error = -EFAULT; |
245 | goto out1; | 242 | goto out1; |
246 | } | 243 | } |
@@ -254,9 +251,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | 251 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, |
255 | 0, DRV_NAME, pdev); | 252 | 0, DRV_NAME, pdev); |
256 | if (error) { | 253 | if (error) { |
257 | printk(KERN_ERR DRV_NAME | 254 | dev_err(&pdev->dev, "unable to claim irq %d\n", |
258 | ": unable to claim irq %d; error %d\n", | 255 | bf54x_kpad->irq); |
259 | bf54x_kpad->irq, error); | ||
260 | goto out2; | 256 | goto out2; |
261 | } | 257 | } |
262 | 258 | ||
@@ -297,8 +293,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
297 | 293 | ||
298 | error = input_register_device(input); | 294 | error = input_register_device(input); |
299 | if (error) { | 295 | if (error) { |
300 | printk(KERN_ERR DRV_NAME | 296 | dev_err(&pdev->dev, "unable to register input device\n"); |
301 | ": Unable to register input device (%d)\n", error); | ||
302 | goto out4; | 297 | goto out4; |
303 | } | 298 | } |
304 | 299 | ||
@@ -316,9 +311,6 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
316 | 311 | ||
317 | device_init_wakeup(&pdev->dev, 1); | 312 | device_init_wakeup(&pdev->dev, 1); |
318 | 313 | ||
319 | printk(KERN_ERR DRV_NAME | ||
320 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
321 | |||
322 | return 0; | 314 | return 0; |
323 | 315 | ||
324 | out4: | 316 | out4: |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index efed0c9e242e..a88aff3816a0 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -216,8 +216,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
216 | 216 | ||
217 | 217 | ||
218 | #ifdef CONFIG_PM | 218 | #ifdef CONFIG_PM |
219 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | 219 | static int gpio_keys_suspend(struct device *dev) |
220 | { | 220 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | ||
221 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 222 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
222 | int i; | 223 | int i; |
223 | 224 | ||
@@ -234,8 +235,9 @@ static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | |||
234 | return 0; | 235 | return 0; |
235 | } | 236 | } |
236 | 237 | ||
237 | static int gpio_keys_resume(struct platform_device *pdev) | 238 | static int gpio_keys_resume(struct device *dev) |
238 | { | 239 | { |
240 | struct platform_device *pdev = to_platform_device(dev); | ||
239 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 241 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
240 | int i; | 242 | int i; |
241 | 243 | ||
@@ -251,19 +253,22 @@ static int gpio_keys_resume(struct platform_device *pdev) | |||
251 | 253 | ||
252 | return 0; | 254 | return 0; |
253 | } | 255 | } |
254 | #else | 256 | |
255 | #define gpio_keys_suspend NULL | 257 | static const struct dev_pm_ops gpio_keys_pm_ops = { |
256 | #define gpio_keys_resume NULL | 258 | .suspend = gpio_keys_suspend, |
259 | .resume = gpio_keys_resume, | ||
260 | }; | ||
257 | #endif | 261 | #endif |
258 | 262 | ||
259 | static struct platform_driver gpio_keys_device_driver = { | 263 | static struct platform_driver gpio_keys_device_driver = { |
260 | .probe = gpio_keys_probe, | 264 | .probe = gpio_keys_probe, |
261 | .remove = __devexit_p(gpio_keys_remove), | 265 | .remove = __devexit_p(gpio_keys_remove), |
262 | .suspend = gpio_keys_suspend, | ||
263 | .resume = gpio_keys_resume, | ||
264 | .driver = { | 266 | .driver = { |
265 | .name = "gpio-keys", | 267 | .name = "gpio-keys", |
266 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
269 | #ifdef CONFIG_PM | ||
270 | .pm = &gpio_keys_pm_ops, | ||
271 | #endif | ||
267 | } | 272 | } |
268 | }; | 273 | }; |
269 | 274 | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 6f356705ee3b..c83f4b2ec7d3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
@@ -37,19 +37,19 @@ | |||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/semaphore.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/pci_ids.h> | 42 | #include <linux/pci_ids.h> |
43 | 43 | ||
44 | #define PREFIX "HIL KEYB: " | 44 | #define PREFIX "HIL: " |
45 | #define HIL_GENERIC_NAME "HIL keyboard" | ||
46 | 45 | ||
47 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | 46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); |
48 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | 47 | MODULE_DESCRIPTION("HIL keyboard/mouse driver"); |
49 | MODULE_LICENSE("Dual BSD/GPL"); | 48 | MODULE_LICENSE("Dual BSD/GPL"); |
50 | MODULE_ALIAS("serio:ty03pr25id00ex*"); | 49 | MODULE_ALIAS("serio:ty03pr25id00ex*"); /* HIL keyboard */ |
50 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); /* HIL mouse */ | ||
51 | 51 | ||
52 | #define HIL_KBD_MAX_LENGTH 16 | 52 | #define HIL_PACKET_MAX_LENGTH 16 |
53 | 53 | ||
54 | #define HIL_KBD_SET1_UPBIT 0x01 | 54 | #define HIL_KBD_SET1_UPBIT 0x01 |
55 | #define HIL_KBD_SET1_SHIFT 1 | 55 | #define HIL_KBD_SET1_SHIFT 1 |
@@ -67,308 +67,497 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = | |||
67 | 67 | ||
68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; | 68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; |
69 | 69 | ||
70 | struct hil_kbd { | 70 | struct hil_dev { |
71 | struct input_dev *dev; | 71 | struct input_dev *dev; |
72 | struct serio *serio; | 72 | struct serio *serio; |
73 | 73 | ||
74 | /* Input buffer and index for packets from HIL bus. */ | 74 | /* Input buffer and index for packets from HIL bus. */ |
75 | hil_packet data[HIL_KBD_MAX_LENGTH]; | 75 | hil_packet data[HIL_PACKET_MAX_LENGTH]; |
76 | int idx4; /* four counts per packet */ | 76 | int idx4; /* four counts per packet */ |
77 | 77 | ||
78 | /* Raw device info records from HIL bus, see hil.h for fields. */ | 78 | /* Raw device info records from HIL bus, see hil.h for fields. */ |
79 | char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ | 79 | char idd[HIL_PACKET_MAX_LENGTH]; /* DID byte and IDD record */ |
80 | char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ | 80 | char rsc[HIL_PACKET_MAX_LENGTH]; /* RSC record */ |
81 | char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ | 81 | char exd[HIL_PACKET_MAX_LENGTH]; /* EXD record */ |
82 | char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | 82 | char rnm[HIL_PACKET_MAX_LENGTH + 1]; /* RNM record + NULL term. */ |
83 | 83 | ||
84 | /* Something to sleep around with. */ | 84 | struct completion cmd_done; |
85 | struct semaphore sem; | 85 | |
86 | bool is_pointer; | ||
87 | /* Extra device details needed for pointing devices. */ | ||
88 | unsigned int nbtn, naxes; | ||
89 | unsigned int btnmap[7]; | ||
86 | }; | 90 | }; |
87 | 91 | ||
88 | /* Process a complete packet after transfer from the HIL */ | 92 | static bool hil_dev_is_command_response(hil_packet p) |
89 | static void hil_kbd_process_record(struct hil_kbd *kbd) | ||
90 | { | 93 | { |
91 | struct input_dev *dev = kbd->dev; | 94 | if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) |
92 | hil_packet *data = kbd->data; | 95 | return false; |
93 | hil_packet p; | ||
94 | int idx, i, cnt; | ||
95 | 96 | ||
96 | idx = kbd->idx4/4; | 97 | if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) |
97 | p = data[idx - 1]; | 98 | return false; |
98 | 99 | ||
99 | if ((p & ~HIL_CMDCT_POL) == | 100 | return true; |
100 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | 101 | } |
101 | goto report; | 102 | |
102 | if ((p & ~HIL_CMDCT_RPL) == | 103 | static void hil_dev_handle_command_response(struct hil_dev *dev) |
103 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | 104 | { |
104 | goto report; | 105 | hil_packet p; |
106 | char *buf; | ||
107 | int i, idx; | ||
108 | |||
109 | idx = dev->idx4 / 4; | ||
110 | p = dev->data[idx - 1]; | ||
105 | 111 | ||
106 | /* Not a poll response. See if we are loading config records. */ | ||
107 | switch (p & HIL_PKT_DATA_MASK) { | 112 | switch (p & HIL_PKT_DATA_MASK) { |
108 | case HIL_CMD_IDD: | 113 | case HIL_CMD_IDD: |
109 | for (i = 0; i < idx; i++) | 114 | buf = dev->idd; |
110 | kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
111 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
112 | kbd->idd[i] = 0; | ||
113 | break; | 115 | break; |
114 | 116 | ||
115 | case HIL_CMD_RSC: | 117 | case HIL_CMD_RSC: |
116 | for (i = 0; i < idx; i++) | 118 | buf = dev->rsc; |
117 | kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
118 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
119 | kbd->rsc[i] = 0; | ||
120 | break; | 119 | break; |
121 | 120 | ||
122 | case HIL_CMD_EXD: | 121 | case HIL_CMD_EXD: |
123 | for (i = 0; i < idx; i++) | 122 | buf = dev->exd; |
124 | kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
125 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
126 | kbd->exd[i] = 0; | ||
127 | break; | 123 | break; |
128 | 124 | ||
129 | case HIL_CMD_RNM: | 125 | case HIL_CMD_RNM: |
130 | for (i = 0; i < idx; i++) | 126 | dev->rnm[HIL_PACKET_MAX_LENGTH] = 0; |
131 | kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | 127 | buf = dev->rnm; |
132 | for (; i < HIL_KBD_MAX_LENGTH + 1; i++) | ||
133 | kbd->rnm[i] = '\0'; | ||
134 | break; | 128 | break; |
135 | 129 | ||
136 | default: | 130 | default: |
137 | /* These occur when device isn't present */ | 131 | /* These occur when device isn't present */ |
138 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | 132 | if (p != (HIL_ERR_INT | HIL_PKT_CMD)) { |
139 | break; | 133 | /* Anything else we'd like to know about. */ |
140 | /* Anything else we'd like to know about. */ | 134 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); |
141 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | 135 | } |
142 | break; | 136 | goto out; |
143 | } | 137 | } |
144 | goto out; | ||
145 | 138 | ||
146 | report: | 139 | for (i = 0; i < idx; i++) |
147 | cnt = 1; | 140 | buf[i] = dev->data[i] & HIL_PKT_DATA_MASK; |
141 | for (; i < HIL_PACKET_MAX_LENGTH; i++) | ||
142 | buf[i] = 0; | ||
143 | out: | ||
144 | complete(&dev->cmd_done); | ||
145 | } | ||
146 | |||
147 | static void hil_dev_handle_kbd_events(struct hil_dev *kbd) | ||
148 | { | ||
149 | struct input_dev *dev = kbd->dev; | ||
150 | int idx = kbd->idx4 / 4; | ||
151 | int i; | ||
152 | |||
148 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { | 153 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { |
149 | case HIL_POL_CHARTYPE_NONE: | 154 | case HIL_POL_CHARTYPE_NONE: |
150 | break; | 155 | return; |
151 | 156 | ||
152 | case HIL_POL_CHARTYPE_ASCII: | 157 | case HIL_POL_CHARTYPE_ASCII: |
153 | while (cnt < idx - 1) | 158 | for (i = 1; i < idx - 1; i++) |
154 | input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); | 159 | input_report_key(dev, kbd->data[i] & 0x7f, 1); |
155 | break; | 160 | break; |
156 | 161 | ||
157 | case HIL_POL_CHARTYPE_RSVD1: | 162 | case HIL_POL_CHARTYPE_RSVD1: |
158 | case HIL_POL_CHARTYPE_RSVD2: | 163 | case HIL_POL_CHARTYPE_RSVD2: |
159 | case HIL_POL_CHARTYPE_BINARY: | 164 | case HIL_POL_CHARTYPE_BINARY: |
160 | while (cnt < idx - 1) | 165 | for (i = 1; i < idx - 1; i++) |
161 | input_report_key(dev, kbd->data[cnt++], 1); | 166 | input_report_key(dev, kbd->data[i], 1); |
162 | break; | 167 | break; |
163 | 168 | ||
164 | case HIL_POL_CHARTYPE_SET1: | 169 | case HIL_POL_CHARTYPE_SET1: |
165 | while (cnt < idx - 1) { | 170 | for (i = 1; i < idx - 1; i++) { |
166 | unsigned int key; | 171 | unsigned int key = kbd->data[i]; |
167 | int up; | 172 | int up = key & HIL_KBD_SET1_UPBIT; |
168 | key = kbd->data[cnt++]; | 173 | |
169 | up = key & HIL_KBD_SET1_UPBIT; | ||
170 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 174 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
171 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; | 175 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; |
172 | if (key != KEY_RESERVED) | 176 | input_report_key(dev, key, !up); |
173 | input_report_key(dev, key, !up); | ||
174 | } | 177 | } |
175 | break; | 178 | break; |
176 | 179 | ||
177 | case HIL_POL_CHARTYPE_SET2: | 180 | case HIL_POL_CHARTYPE_SET2: |
178 | while (cnt < idx - 1) { | 181 | for (i = 1; i < idx - 1; i++) { |
179 | unsigned int key; | 182 | unsigned int key = kbd->data[i]; |
180 | int up; | 183 | int up = key & HIL_KBD_SET2_UPBIT; |
181 | key = kbd->data[cnt++]; | 184 | |
182 | up = key & HIL_KBD_SET2_UPBIT; | ||
183 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 185 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
184 | key = key >> HIL_KBD_SET2_SHIFT; | 186 | key = key >> HIL_KBD_SET2_SHIFT; |
185 | if (key != KEY_RESERVED) | 187 | input_report_key(dev, key, !up); |
186 | input_report_key(dev, key, !up); | ||
187 | } | 188 | } |
188 | break; | 189 | break; |
189 | 190 | ||
190 | case HIL_POL_CHARTYPE_SET3: | 191 | case HIL_POL_CHARTYPE_SET3: |
191 | while (cnt < idx - 1) { | 192 | for (i = 1; i < idx - 1; i++) { |
192 | unsigned int key; | 193 | unsigned int key = kbd->data[i]; |
193 | int up; | 194 | int up = key & HIL_KBD_SET3_UPBIT; |
194 | key = kbd->data[cnt++]; | 195 | |
195 | up = key & HIL_KBD_SET3_UPBIT; | ||
196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; | 197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; |
198 | if (key != KEY_RESERVED) | 198 | input_report_key(dev, key, !up); |
199 | input_report_key(dev, key, !up); | ||
200 | } | 199 | } |
201 | break; | 200 | break; |
202 | } | 201 | } |
203 | out: | 202 | |
204 | kbd->idx4 = 0; | 203 | input_sync(dev); |
205 | up(&kbd->sem); | ||
206 | } | 204 | } |
207 | 205 | ||
208 | static void hil_kbd_process_err(struct hil_kbd *kbd) | 206 | static void hil_dev_handle_ptr_events(struct hil_dev *ptr) |
207 | { | ||
208 | struct input_dev *dev = ptr->dev; | ||
209 | int idx = ptr->idx4 / 4; | ||
210 | hil_packet p = ptr->data[idx - 1]; | ||
211 | int i, cnt, laxis; | ||
212 | bool absdev, ax16; | ||
213 | |||
214 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
215 | printk(KERN_WARNING PREFIX | ||
216 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | i = (p & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
221 | laxis = (p & HIL_POL_NUM_AXES_MASK) + i; | ||
222 | |||
223 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
224 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
225 | |||
226 | for (cnt = 1; i < laxis; i++) { | ||
227 | unsigned int lo, hi, val; | ||
228 | |||
229 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
230 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
231 | |||
232 | if (absdev) { | ||
233 | val = lo + (hi << 8); | ||
234 | #ifdef TABLET_AUTOADJUST | ||
235 | if (val < dev->absmin[ABS_X + i]) | ||
236 | dev->absmin[ABS_X + i] = val; | ||
237 | if (val > dev->absmax[ABS_X + i]) | ||
238 | dev->absmax[ABS_X + i] = val; | ||
239 | #endif | ||
240 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
241 | input_report_abs(dev, ABS_X + i, val); | ||
242 | } else { | ||
243 | val = (int) (((int8_t)lo) | ((int8_t)hi << 8)); | ||
244 | if (i % 3) | ||
245 | val *= -1; | ||
246 | input_report_rel(dev, REL_X + i, val); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | while (cnt < idx - 1) { | ||
251 | unsigned int btn = ptr->data[cnt++]; | ||
252 | int up = btn & 1; | ||
253 | |||
254 | btn &= 0xfe; | ||
255 | if (btn == 0x8e) | ||
256 | continue; /* TODO: proximity == touch? */ | ||
257 | if (btn > 0x8c || btn < 0x80) | ||
258 | continue; | ||
259 | btn = (btn - 0x80) >> 1; | ||
260 | btn = ptr->btnmap[btn]; | ||
261 | input_report_key(dev, btn, !up); | ||
262 | } | ||
263 | |||
264 | input_sync(dev); | ||
265 | } | ||
266 | |||
267 | static void hil_dev_process_err(struct hil_dev *dev) | ||
209 | { | 268 | { |
210 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | 269 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); |
211 | kbd->idx4 = 0; | 270 | dev->idx4 = 0; |
212 | up(&kbd->sem); | 271 | complete(&dev->cmd_done); /* just in case somebody is waiting */ |
213 | } | 272 | } |
214 | 273 | ||
215 | static irqreturn_t hil_kbd_interrupt(struct serio *serio, | 274 | static irqreturn_t hil_dev_interrupt(struct serio *serio, |
216 | unsigned char data, unsigned int flags) | 275 | unsigned char data, unsigned int flags) |
217 | { | 276 | { |
218 | struct hil_kbd *kbd; | 277 | struct hil_dev *dev; |
219 | hil_packet packet; | 278 | hil_packet packet; |
220 | int idx; | 279 | int idx; |
221 | 280 | ||
222 | kbd = serio_get_drvdata(serio); | 281 | dev = serio_get_drvdata(serio); |
223 | BUG_ON(kbd == NULL); | 282 | BUG_ON(dev == NULL); |
224 | 283 | ||
225 | if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { | 284 | if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) { |
226 | hil_kbd_process_err(kbd); | 285 | hil_dev_process_err(dev); |
227 | return IRQ_HANDLED; | 286 | goto out; |
228 | } | 287 | } |
229 | idx = kbd->idx4/4; | 288 | |
230 | if (!(kbd->idx4 % 4)) | 289 | idx = dev->idx4 / 4; |
231 | kbd->data[idx] = 0; | 290 | if (!(dev->idx4 % 4)) |
232 | packet = kbd->data[idx]; | 291 | dev->data[idx] = 0; |
233 | packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); | 292 | packet = dev->data[idx]; |
234 | kbd->data[idx] = packet; | 293 | packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8); |
294 | dev->data[idx] = packet; | ||
235 | 295 | ||
236 | /* Records of N 4-byte hil_packets must terminate with a command. */ | 296 | /* Records of N 4-byte hil_packets must terminate with a command. */ |
237 | if ((++(kbd->idx4)) % 4) | 297 | if ((++dev->idx4 % 4) == 0) { |
238 | return IRQ_HANDLED; | 298 | if ((packet & 0xffff0000) != HIL_ERR_INT) { |
239 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | 299 | hil_dev_process_err(dev); |
240 | hil_kbd_process_err(kbd); | 300 | } else if (packet & HIL_PKT_CMD) { |
241 | return IRQ_HANDLED; | 301 | if (hil_dev_is_command_response(packet)) |
302 | hil_dev_handle_command_response(dev); | ||
303 | else if (dev->is_pointer) | ||
304 | hil_dev_handle_ptr_events(dev); | ||
305 | else | ||
306 | hil_dev_handle_kbd_events(dev); | ||
307 | dev->idx4 = 0; | ||
308 | } | ||
242 | } | 309 | } |
243 | if (packet & HIL_PKT_CMD) | 310 | out: |
244 | hil_kbd_process_record(kbd); | ||
245 | return IRQ_HANDLED; | 311 | return IRQ_HANDLED; |
246 | } | 312 | } |
247 | 313 | ||
248 | static void hil_kbd_disconnect(struct serio *serio) | 314 | static void hil_dev_disconnect(struct serio *serio) |
249 | { | 315 | { |
250 | struct hil_kbd *kbd; | 316 | struct hil_dev *dev = serio_get_drvdata(serio); |
251 | 317 | ||
252 | kbd = serio_get_drvdata(serio); | 318 | BUG_ON(dev == NULL); |
253 | BUG_ON(kbd == NULL); | ||
254 | 319 | ||
255 | serio_close(serio); | 320 | serio_close(serio); |
256 | input_unregister_device(kbd->dev); | 321 | input_unregister_device(dev->dev); |
257 | kfree(kbd); | 322 | serio_set_drvdata(serio, NULL); |
323 | kfree(dev); | ||
324 | } | ||
325 | |||
326 | static void hil_dev_keyboard_setup(struct hil_dev *kbd) | ||
327 | { | ||
328 | struct input_dev *input_dev = kbd->dev; | ||
329 | uint8_t did = kbd->idd[0]; | ||
330 | int i; | ||
331 | |||
332 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
333 | input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | ||
334 | BIT_MASK(LED_SCROLLL); | ||
335 | |||
336 | for (i = 0; i < 128; i++) { | ||
337 | __set_bit(hil_kbd_set1[i], input_dev->keybit); | ||
338 | __set_bit(hil_kbd_set3[i], input_dev->keybit); | ||
339 | } | ||
340 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
341 | |||
342 | input_dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | ||
343 | input_dev->keycodesize = sizeof(hil_kbd_set1[0]); | ||
344 | input_dev->keycode = hil_kbd_set1; | ||
345 | |||
346 | input_dev->name = strlen(kbd->rnm) ? kbd->rnm : "HIL keyboard"; | ||
347 | input_dev->phys = "hpkbd/input0"; | ||
348 | |||
349 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | ||
350 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | ||
258 | } | 351 | } |
259 | 352 | ||
260 | static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) | 353 | static void hil_dev_pointer_setup(struct hil_dev *ptr) |
261 | { | 354 | { |
262 | struct hil_kbd *kbd; | 355 | struct input_dev *input_dev = ptr->dev; |
263 | uint8_t did, *idd; | 356 | uint8_t did = ptr->idd[0]; |
264 | int i; | 357 | uint8_t *idd = ptr->idd + 1; |
358 | unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
359 | unsigned int i, btntype; | ||
360 | const char *txt; | ||
361 | |||
362 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
363 | |||
364 | switch (did & HIL_IDD_DID_TYPE_MASK) { | ||
365 | case HIL_IDD_DID_TYPE_REL: | ||
366 | input_dev->evbit[0] = BIT_MASK(EV_REL); | ||
265 | 367 | ||
266 | kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); | 368 | for (i = 0; i < ptr->naxes; i++) |
267 | if (!kbd) | 369 | __set_bit(REL_X + i, input_dev->relbit); |
268 | return -ENOMEM; | ||
269 | 370 | ||
270 | kbd->dev = input_allocate_device(); | 371 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) |
271 | if (!kbd->dev) | 372 | __set_bit(REL_X + i, input_dev->relbit); |
373 | |||
374 | txt = "relative"; | ||
375 | break; | ||
376 | |||
377 | case HIL_IDD_DID_TYPE_ABS: | ||
378 | input_dev->evbit[0] = BIT_MASK(EV_ABS); | ||
379 | |||
380 | for (i = 0; i < ptr->naxes; i++) | ||
381 | input_set_abs_params(input_dev, ABS_X + i, | ||
382 | 0, HIL_IDD_AXIS_MAX(idd, i), 0, 0); | ||
383 | |||
384 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) | ||
385 | input_set_abs_params(input_dev, ABS_X + i, | ||
386 | 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0); | ||
387 | |||
388 | #ifdef TABLET_AUTOADJUST | ||
389 | for (i = 0; i < ABS_MAX; i++) { | ||
390 | int diff = input_dev->absmax[ABS_X + i] / 10; | ||
391 | input_dev->absmin[ABS_X + i] += diff; | ||
392 | input_dev->absmax[ABS_X + i] -= diff; | ||
393 | } | ||
394 | #endif | ||
395 | |||
396 | txt = "absolute"; | ||
397 | break; | ||
398 | |||
399 | default: | ||
400 | BUG(); | ||
401 | } | ||
402 | |||
403 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
404 | if (ptr->nbtn) | ||
405 | input_dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
406 | |||
407 | btntype = BTN_MISC; | ||
408 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
409 | #ifdef TABLET_SIMULATES_MOUSE | ||
410 | btntype = BTN_TOUCH; | ||
411 | #else | ||
412 | btntype = BTN_DIGI; | ||
413 | #endif | ||
414 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
415 | btntype = BTN_TOUCH; | ||
416 | |||
417 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
418 | btntype = BTN_MOUSE; | ||
419 | |||
420 | for (i = 0; i < ptr->nbtn; i++) { | ||
421 | __set_bit(btntype | i, input_dev->keybit); | ||
422 | ptr->btnmap[i] = btntype | i; | ||
423 | } | ||
424 | |||
425 | if (btntype == BTN_MOUSE) { | ||
426 | /* Swap buttons 2 and 3 */ | ||
427 | ptr->btnmap[1] = BTN_MIDDLE; | ||
428 | ptr->btnmap[2] = BTN_RIGHT; | ||
429 | } | ||
430 | |||
431 | input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device"; | ||
432 | |||
433 | printk(KERN_INFO PREFIX | ||
434 | "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
435 | did, txt); | ||
436 | printk(KERN_INFO PREFIX | ||
437 | "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
438 | ptr->nbtn, naxsets, ptr->naxes); | ||
439 | } | ||
440 | |||
441 | static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | ||
442 | { | ||
443 | struct hil_dev *dev; | ||
444 | struct input_dev *input_dev; | ||
445 | uint8_t did, *idd; | ||
446 | int error; | ||
447 | |||
448 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
449 | input_dev = input_allocate_device(); | ||
450 | if (!dev || !input_dev) { | ||
451 | error = -ENOMEM; | ||
272 | goto bail0; | 452 | goto bail0; |
453 | } | ||
273 | 454 | ||
274 | if (serio_open(serio, drv)) | 455 | dev->serio = serio; |
275 | goto bail1; | 456 | dev->dev = input_dev; |
276 | 457 | ||
277 | serio_set_drvdata(serio, kbd); | 458 | error = serio_open(serio, drv); |
278 | kbd->serio = serio; | 459 | if (error) |
460 | goto bail0; | ||
279 | 461 | ||
280 | init_MUTEX_LOCKED(&kbd->sem); | 462 | serio_set_drvdata(serio, dev); |
281 | 463 | ||
282 | /* Get device info. MLC driver supplies devid/status/etc. */ | 464 | /* Get device info. MLC driver supplies devid/status/etc. */ |
283 | serio->write(serio, 0); | 465 | init_completion(&dev->cmd_done); |
284 | serio->write(serio, 0); | 466 | serio_write(serio, 0); |
285 | serio->write(serio, HIL_PKT_CMD >> 8); | 467 | serio_write(serio, 0); |
286 | serio->write(serio, HIL_CMD_IDD); | 468 | serio_write(serio, HIL_PKT_CMD >> 8); |
287 | down(&kbd->sem); | 469 | serio_write(serio, HIL_CMD_IDD); |
288 | 470 | error = wait_for_completion_killable(&dev->cmd_done); | |
289 | serio->write(serio, 0); | 471 | if (error) |
290 | serio->write(serio, 0); | 472 | goto bail1; |
291 | serio->write(serio, HIL_PKT_CMD >> 8); | 473 | |
292 | serio->write(serio, HIL_CMD_RSC); | 474 | init_completion(&dev->cmd_done); |
293 | down(&kbd->sem); | 475 | serio_write(serio, 0); |
294 | 476 | serio_write(serio, 0); | |
295 | serio->write(serio, 0); | 477 | serio_write(serio, HIL_PKT_CMD >> 8); |
296 | serio->write(serio, 0); | 478 | serio_write(serio, HIL_CMD_RSC); |
297 | serio->write(serio, HIL_PKT_CMD >> 8); | 479 | error = wait_for_completion_killable(&dev->cmd_done); |
298 | serio->write(serio, HIL_CMD_RNM); | 480 | if (error) |
299 | down(&kbd->sem); | 481 | goto bail1; |
300 | 482 | ||
301 | serio->write(serio, 0); | 483 | init_completion(&dev->cmd_done); |
302 | serio->write(serio, 0); | 484 | serio_write(serio, 0); |
303 | serio->write(serio, HIL_PKT_CMD >> 8); | 485 | serio_write(serio, 0); |
304 | serio->write(serio, HIL_CMD_EXD); | 486 | serio_write(serio, HIL_PKT_CMD >> 8); |
305 | down(&kbd->sem); | 487 | serio_write(serio, HIL_CMD_RNM); |
306 | 488 | error = wait_for_completion_killable(&dev->cmd_done); | |
307 | up(&kbd->sem); | 489 | if (error) |
308 | 490 | goto bail1; | |
309 | did = kbd->idd[0]; | 491 | |
310 | idd = kbd->idd + 1; | 492 | init_completion(&dev->cmd_done); |
493 | serio_write(serio, 0); | ||
494 | serio_write(serio, 0); | ||
495 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
496 | serio_write(serio, HIL_CMD_EXD); | ||
497 | error = wait_for_completion_killable(&dev->cmd_done); | ||
498 | if (error) | ||
499 | goto bail1; | ||
500 | |||
501 | did = dev->idd[0]; | ||
502 | idd = dev->idd + 1; | ||
503 | |||
311 | switch (did & HIL_IDD_DID_TYPE_MASK) { | 504 | switch (did & HIL_IDD_DID_TYPE_MASK) { |
312 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: | 505 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: |
313 | case HIL_IDD_DID_TYPE_KB_ITF: | 506 | case HIL_IDD_DID_TYPE_KB_ITF: |
314 | case HIL_IDD_DID_TYPE_KB_RSVD: | 507 | case HIL_IDD_DID_TYPE_KB_RSVD: |
315 | case HIL_IDD_DID_TYPE_CHAR: | 508 | case HIL_IDD_DID_TYPE_CHAR: |
316 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | 509 | if (HIL_IDD_NUM_BUTTONS(idd) || |
317 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | 510 | HIL_IDD_NUM_AXES_PER_SET(*idd)) { |
318 | break; | 511 | printk(KERN_INFO PREFIX |
319 | default: | 512 | "combo devices are not supported.\n"); |
320 | goto bail2; | 513 | goto bail1; |
321 | } | 514 | } |
322 | 515 | ||
323 | if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { | 516 | dev->is_pointer = false; |
324 | printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); | 517 | hil_dev_keyboard_setup(dev); |
325 | goto bail2; | 518 | break; |
326 | } | ||
327 | 519 | ||
328 | kbd->dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 520 | case HIL_IDD_DID_TYPE_REL: |
329 | kbd->dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 521 | case HIL_IDD_DID_TYPE_ABS: |
330 | BIT_MASK(LED_SCROLLL); | 522 | dev->is_pointer = true; |
331 | kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 523 | hil_dev_pointer_setup(dev); |
332 | kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); | 524 | break; |
333 | kbd->dev->keycode = hil_kbd_set1; | ||
334 | kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; | ||
335 | kbd->dev->phys = "hpkbd/input0"; /* XXX */ | ||
336 | |||
337 | kbd->dev->id.bustype = BUS_HIL; | ||
338 | kbd->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
339 | kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ | ||
340 | kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
341 | kbd->dev->dev.parent = &serio->dev; | ||
342 | 525 | ||
343 | for (i = 0; i < 128; i++) { | 526 | default: |
344 | set_bit(hil_kbd_set1[i], kbd->dev->keybit); | 527 | goto bail1; |
345 | set_bit(hil_kbd_set3[i], kbd->dev->keybit); | ||
346 | } | 528 | } |
347 | clear_bit(0, kbd->dev->keybit); | ||
348 | 529 | ||
349 | input_register_device(kbd->dev); | 530 | input_dev->id.bustype = BUS_HIL; |
350 | printk(KERN_INFO "input: %s, ID: %d\n", | 531 | input_dev->id.vendor = PCI_VENDOR_ID_HP; |
351 | kbd->dev->name, did); | 532 | input_dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ |
533 | input_dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
534 | input_dev->dev.parent = &serio->dev; | ||
535 | |||
536 | if (!dev->is_pointer) { | ||
537 | serio_write(serio, 0); | ||
538 | serio_write(serio, 0); | ||
539 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
540 | /* Enable Keyswitch Autorepeat 1 */ | ||
541 | serio_write(serio, HIL_CMD_EK1); | ||
542 | /* No need to wait for completion */ | ||
543 | } | ||
352 | 544 | ||
353 | serio->write(serio, 0); | 545 | error = input_register_device(input_dev); |
354 | serio->write(serio, 0); | 546 | if (error) |
355 | serio->write(serio, HIL_PKT_CMD >> 8); | 547 | goto bail1; |
356 | serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ | ||
357 | down(&kbd->sem); | ||
358 | up(&kbd->sem); | ||
359 | 548 | ||
360 | return 0; | 549 | return 0; |
361 | bail2: | 550 | |
551 | bail1: | ||
362 | serio_close(serio); | 552 | serio_close(serio); |
363 | serio_set_drvdata(serio, NULL); | 553 | serio_set_drvdata(serio, NULL); |
364 | bail1: | ||
365 | input_free_device(kbd->dev); | ||
366 | bail0: | 554 | bail0: |
367 | kfree(kbd); | 555 | input_free_device(input_dev); |
368 | return -EIO; | 556 | kfree(dev); |
557 | return error; | ||
369 | } | 558 | } |
370 | 559 | ||
371 | static struct serio_device_id hil_kbd_ids[] = { | 560 | static struct serio_device_id hil_dev_ids[] = { |
372 | { | 561 | { |
373 | .type = SERIO_HIL_MLC, | 562 | .type = SERIO_HIL_MLC, |
374 | .proto = SERIO_HIL, | 563 | .proto = SERIO_HIL, |
@@ -378,26 +567,26 @@ static struct serio_device_id hil_kbd_ids[] = { | |||
378 | { 0 } | 567 | { 0 } |
379 | }; | 568 | }; |
380 | 569 | ||
381 | static struct serio_driver hil_kbd_serio_drv = { | 570 | static struct serio_driver hil_serio_drv = { |
382 | .driver = { | 571 | .driver = { |
383 | .name = "hil_kbd", | 572 | .name = "hil_dev", |
384 | }, | 573 | }, |
385 | .description = "HP HIL keyboard driver", | 574 | .description = "HP HIL keyboard/mouse/tablet driver", |
386 | .id_table = hil_kbd_ids, | 575 | .id_table = hil_dev_ids, |
387 | .connect = hil_kbd_connect, | 576 | .connect = hil_dev_connect, |
388 | .disconnect = hil_kbd_disconnect, | 577 | .disconnect = hil_dev_disconnect, |
389 | .interrupt = hil_kbd_interrupt | 578 | .interrupt = hil_dev_interrupt |
390 | }; | 579 | }; |
391 | 580 | ||
392 | static int __init hil_kbd_init(void) | 581 | static int __init hil_dev_init(void) |
393 | { | 582 | { |
394 | return serio_register_driver(&hil_kbd_serio_drv); | 583 | return serio_register_driver(&hil_serio_drv); |
395 | } | 584 | } |
396 | 585 | ||
397 | static void __exit hil_kbd_exit(void) | 586 | static void __exit hil_dev_exit(void) |
398 | { | 587 | { |
399 | serio_unregister_driver(&hil_kbd_serio_drv); | 588 | serio_unregister_driver(&hil_serio_drv); |
400 | } | 589 | } |
401 | 590 | ||
402 | module_init(hil_kbd_init); | 591 | module_init(hil_dev_init); |
403 | module_exit(hil_kbd_exit); | 592 | module_exit(hil_dev_exit); |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 4730ef35c732..f9847e0fb553 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -525,12 +525,12 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
527 | if (leds_on != 0) { | 527 | if (leds_on != 0) { |
528 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 528 | serio_write (lk->serio, LK_CMD_LED_ON); |
529 | lk->serio->write (lk->serio, leds_on); | 529 | serio_write (lk->serio, leds_on); |
530 | } | 530 | } |
531 | if (leds_off != 0) { | 531 | if (leds_off != 0) { |
532 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 532 | serio_write (lk->serio, LK_CMD_LED_OFF); |
533 | lk->serio->write (lk->serio, leds_off); | 533 | serio_write (lk->serio, leds_off); |
534 | } | 534 | } |
535 | return 0; | 535 | return 0; |
536 | 536 | ||
@@ -539,20 +539,20 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
539 | case SND_CLICK: | 539 | case SND_CLICK: |
540 | if (value == 0) { | 540 | if (value == 0) { |
541 | DBG ("%s: Deactivating key clicks\n", __func__); | 541 | DBG ("%s: Deactivating key clicks\n", __func__); |
542 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 542 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
543 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 543 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
544 | } else { | 544 | } else { |
545 | DBG ("%s: Activating key clicks\n", __func__); | 545 | DBG ("%s: Activating key clicks\n", __func__); |
546 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 546 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
547 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 547 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
548 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 548 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
549 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 549 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
550 | } | 550 | } |
551 | return 0; | 551 | return 0; |
552 | 552 | ||
553 | case SND_BELL: | 553 | case SND_BELL: |
554 | if (value != 0) | 554 | if (value != 0) |
555 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 555 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
556 | 556 | ||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
@@ -579,10 +579,10 @@ lkkbd_reinit (struct work_struct *work) | |||
579 | unsigned char leds_off = 0; | 579 | unsigned char leds_off = 0; |
580 | 580 | ||
581 | /* Ask for ID */ | 581 | /* Ask for ID */ |
582 | lk->serio->write (lk->serio, LK_CMD_REQUEST_ID); | 582 | serio_write (lk->serio, LK_CMD_REQUEST_ID); |
583 | 583 | ||
584 | /* Reset parameters */ | 584 | /* Reset parameters */ |
585 | lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); | 585 | serio_write (lk->serio, LK_CMD_SET_DEFAULTS); |
586 | 586 | ||
587 | /* Set LEDs */ | 587 | /* Set LEDs */ |
588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); |
@@ -590,12 +590,12 @@ lkkbd_reinit (struct work_struct *work) | |||
590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
592 | if (leds_on != 0) { | 592 | if (leds_on != 0) { |
593 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 593 | serio_write (lk->serio, LK_CMD_LED_ON); |
594 | lk->serio->write (lk->serio, leds_on); | 594 | serio_write (lk->serio, leds_on); |
595 | } | 595 | } |
596 | if (leds_off != 0) { | 596 | if (leds_off != 0) { |
597 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 597 | serio_write (lk->serio, LK_CMD_LED_OFF); |
598 | lk->serio->write (lk->serio, leds_off); | 598 | serio_write (lk->serio, leds_off); |
599 | } | 599 | } |
600 | 600 | ||
601 | /* | 601 | /* |
@@ -603,31 +603,31 @@ lkkbd_reinit (struct work_struct *work) | |||
603 | * only work with a LK401 keyboard and grants access to | 603 | * only work with a LK401 keyboard and grants access to |
604 | * LAlt, RAlt, RCompose and RShift. | 604 | * LAlt, RAlt, RCompose and RShift. |
605 | */ | 605 | */ |
606 | lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401); | 606 | serio_write (lk->serio, LK_CMD_ENABLE_LK401); |
607 | 607 | ||
608 | /* Set all keys to UPDOWN mode */ | 608 | /* Set all keys to UPDOWN mode */ |
609 | for (division = 1; division <= 14; division++) | 609 | for (division = 1; division <= 14; division++) |
610 | lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, | 610 | serio_write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, |
611 | division)); | 611 | division)); |
612 | 612 | ||
613 | /* Enable bell and set volume */ | 613 | /* Enable bell and set volume */ |
614 | lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL); | 614 | serio_write (lk->serio, LK_CMD_ENABLE_BELL); |
615 | lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); | 615 | serio_write (lk->serio, volume_to_hw (lk->bell_volume)); |
616 | 616 | ||
617 | /* Enable/disable keyclick (and possibly set volume) */ | 617 | /* Enable/disable keyclick (and possibly set volume) */ |
618 | if (test_bit (SND_CLICK, lk->dev->snd)) { | 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { |
619 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 619 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
620 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 620 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
621 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 621 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
622 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 622 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
623 | } else { | 623 | } else { |
624 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 624 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
625 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 625 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
626 | } | 626 | } |
627 | 627 | ||
628 | /* Sound the bell if needed */ | 628 | /* Sound the bell if needed */ |
629 | if (test_bit (SND_BELL, lk->dev->snd)) | 629 | if (test_bit (SND_BELL, lk->dev->snd)) |
630 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 630 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
631 | } | 631 | } |
632 | 632 | ||
633 | /* | 633 | /* |
@@ -684,8 +684,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
684 | input_dev->keycode = lk->keycode; | 684 | input_dev->keycode = lk->keycode; |
685 | input_dev->keycodesize = sizeof (lk_keycode_t); | 685 | input_dev->keycodesize = sizeof (lk_keycode_t); |
686 | input_dev->keycodemax = LK_NUM_KEYCODES; | 686 | input_dev->keycodemax = LK_NUM_KEYCODES; |
687 | |||
687 | for (i = 0; i < LK_NUM_KEYCODES; i++) | 688 | for (i = 0; i < LK_NUM_KEYCODES; i++) |
688 | set_bit (lk->keycode[i], input_dev->keybit); | 689 | __set_bit (lk->keycode[i], input_dev->keybit); |
690 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
689 | 691 | ||
690 | serio_set_drvdata (serio, lk); | 692 | serio_set_drvdata (serio, lk); |
691 | 693 | ||
@@ -697,7 +699,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
697 | if (err) | 699 | if (err) |
698 | goto fail3; | 700 | goto fail3; |
699 | 701 | ||
700 | lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); | 702 | serio_write (lk->serio, LK_CMD_POWERCYCLE_RESET); |
701 | 703 | ||
702 | return 0; | 704 | return 0; |
703 | 705 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 541b981ff075..91cfe5170265 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -319,7 +319,6 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
319 | struct input_dev *input_dev; | 319 | struct input_dev *input_dev; |
320 | unsigned short *keycodes; | 320 | unsigned short *keycodes; |
321 | unsigned int row_shift; | 321 | unsigned int row_shift; |
322 | int i; | ||
323 | int err; | 322 | int err; |
324 | 323 | ||
325 | pdata = pdev->dev.platform_data; | 324 | pdata = pdev->dev.platform_data; |
@@ -363,18 +362,10 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
363 | 362 | ||
364 | input_dev->keycode = keycodes; | 363 | input_dev->keycode = keycodes; |
365 | input_dev->keycodesize = sizeof(*keycodes); | 364 | input_dev->keycodesize = sizeof(*keycodes); |
366 | input_dev->keycodemax = pdata->num_row_gpios << keypad->row_shift; | 365 | input_dev->keycodemax = pdata->num_row_gpios << row_shift; |
367 | |||
368 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
369 | unsigned int key = keymap_data->keymap[i]; | ||
370 | unsigned int row = KEY_ROW(key); | ||
371 | unsigned int col = KEY_COL(key); | ||
372 | unsigned short code = KEY_VAL(key); | ||
373 | 366 | ||
374 | keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | 367 | matrix_keypad_build_keymap(keymap_data, row_shift, |
375 | __set_bit(code, input_dev->keybit); | 368 | input_dev->keycode, input_dev->keybit); |
376 | } | ||
377 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
378 | 369 | ||
379 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 370 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
380 | input_set_drvdata(input_dev, keypad); | 371 | input_set_drvdata(input_dev, keypad); |
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 0d2fc64a5e1c..79cd3e9fdf2e 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Based on a previous implementations by Kevin O'Connor | 9 | * Based on a previous implementations by Kevin O'Connor |
10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and | 10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and |
11 | * on some suggestions by Nicolas Pitre <nico@cam.org>. | 11 | * on some suggestions by Nicolas Pitre <nico@fluxnic.net>. |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
@@ -25,13 +25,13 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/input/matrix_keypad.h> | ||
28 | 29 | ||
29 | #include <asm/mach/arch.h> | 30 | #include <asm/mach/arch.h> |
30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
31 | 32 | ||
32 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
33 | #include <mach/pxa27x_keypad.h> | 34 | #include <mach/pxa27x_keypad.h> |
34 | |||
35 | /* | 35 | /* |
36 | * Keypad Controller registers | 36 | * Keypad Controller registers |
37 | */ | 37 | */ |
@@ -95,7 +95,8 @@ | |||
95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | 95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) |
96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) | 96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) |
97 | 97 | ||
98 | #define MAX_MATRIX_KEY_NUM (8 * 8) | 98 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) |
99 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) | ||
99 | 100 | ||
100 | struct pxa27x_keypad { | 101 | struct pxa27x_keypad { |
101 | struct pxa27x_keypad_platform_data *pdata; | 102 | struct pxa27x_keypad_platform_data *pdata; |
@@ -106,73 +107,82 @@ struct pxa27x_keypad { | |||
106 | 107 | ||
107 | int irq; | 108 | int irq; |
108 | 109 | ||
109 | /* matrix key code map */ | 110 | unsigned short keycodes[MAX_KEYPAD_KEYS]; |
110 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 111 | int rotary_rel_code[2]; |
111 | 112 | ||
112 | /* state row bits of each column scan */ | 113 | /* state row bits of each column scan */ |
113 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; | 114 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; |
114 | uint32_t direct_key_state; | 115 | uint32_t direct_key_state; |
115 | 116 | ||
116 | unsigned int direct_key_mask; | 117 | unsigned int direct_key_mask; |
117 | |||
118 | int rotary_rel_code[2]; | ||
119 | int rotary_up_key[2]; | ||
120 | int rotary_down_key[2]; | ||
121 | }; | 118 | }; |
122 | 119 | ||
123 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 120 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) |
124 | { | 121 | { |
125 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 122 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
126 | struct input_dev *input_dev = keypad->input_dev; | 123 | struct input_dev *input_dev = keypad->input_dev; |
127 | unsigned int *key; | 124 | unsigned short keycode; |
128 | int i; | 125 | int i; |
129 | 126 | ||
130 | key = &pdata->matrix_key_map[0]; | 127 | for (i = 0; i < pdata->matrix_key_map_size; i++) { |
131 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | 128 | unsigned int key = pdata->matrix_key_map[i]; |
132 | int row = ((*key) >> 28) & 0xf; | 129 | unsigned int row = KEY_ROW(key); |
133 | int col = ((*key) >> 24) & 0xf; | 130 | unsigned int col = KEY_COL(key); |
134 | int code = (*key) & 0xffffff; | 131 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, |
132 | MATRIX_ROW_SHIFT); | ||
135 | 133 | ||
136 | keypad->matrix_keycodes[(row << 3) + col] = code; | 134 | keycode = KEY_VAL(key); |
137 | set_bit(code, input_dev->keybit); | 135 | keypad->keycodes[scancode] = keycode; |
136 | __set_bit(keycode, input_dev->keybit); | ||
138 | } | 137 | } |
139 | 138 | ||
140 | for (i = 0; i < pdata->direct_key_num; i++) | 139 | for (i = 0; i < pdata->direct_key_num; i++) { |
141 | set_bit(pdata->direct_key_map[i], input_dev->keybit); | 140 | keycode = pdata->direct_key_map[i]; |
142 | 141 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; | |
143 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; | 142 | __set_bit(keycode, input_dev->keybit); |
144 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; | 143 | } |
145 | keypad->rotary_down_key[0] = pdata->rotary0_down_key; | ||
146 | keypad->rotary_down_key[1] = pdata->rotary1_down_key; | ||
147 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
148 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
149 | 144 | ||
150 | if (pdata->enable_rotary0) { | 145 | if (pdata->enable_rotary0) { |
151 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { | 146 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { |
152 | set_bit(pdata->rotary0_up_key, input_dev->keybit); | 147 | keycode = pdata->rotary0_up_key; |
153 | set_bit(pdata->rotary0_down_key, input_dev->keybit); | 148 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 0] = keycode; |
154 | } else | 149 | __set_bit(keycode, input_dev->keybit); |
155 | set_bit(pdata->rotary0_rel_code, input_dev->relbit); | 150 | |
151 | keycode = pdata->rotary0_down_key; | ||
152 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 1] = keycode; | ||
153 | __set_bit(keycode, input_dev->keybit); | ||
154 | |||
155 | keypad->rotary_rel_code[0] = -1; | ||
156 | } else { | ||
157 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
158 | __set_bit(pdata->rotary0_rel_code, input_dev->relbit); | ||
159 | } | ||
156 | } | 160 | } |
157 | 161 | ||
158 | if (pdata->enable_rotary1) { | 162 | if (pdata->enable_rotary1) { |
159 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { | 163 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { |
160 | set_bit(pdata->rotary1_up_key, input_dev->keybit); | 164 | keycode = pdata->rotary1_up_key; |
161 | set_bit(pdata->rotary1_down_key, input_dev->keybit); | 165 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 2] = keycode; |
162 | } else | 166 | __set_bit(keycode, input_dev->keybit); |
163 | set_bit(pdata->rotary1_rel_code, input_dev->relbit); | 167 | |
168 | keycode = pdata->rotary1_down_key; | ||
169 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 3] = keycode; | ||
170 | __set_bit(keycode, input_dev->keybit); | ||
171 | |||
172 | keypad->rotary_rel_code[1] = -1; | ||
173 | } else { | ||
174 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
175 | __set_bit(pdata->rotary1_rel_code, input_dev->relbit); | ||
176 | } | ||
164 | } | 177 | } |
165 | } | ||
166 | 178 | ||
167 | static inline unsigned int lookup_matrix_keycode( | 179 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
168 | struct pxa27x_keypad *keypad, int row, int col) | ||
169 | { | ||
170 | return keypad->matrix_keycodes[(row << 3) + col]; | ||
171 | } | 180 | } |
172 | 181 | ||
173 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | 182 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) |
174 | { | 183 | { |
175 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 184 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
185 | struct input_dev *input_dev = keypad->input_dev; | ||
176 | int row, col, num_keys_pressed = 0; | 186 | int row, col, num_keys_pressed = 0; |
177 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 187 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
178 | uint32_t kpas = keypad_readl(KPAS); | 188 | uint32_t kpas = keypad_readl(KPAS); |
@@ -215,6 +225,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | |||
215 | scan: | 225 | scan: |
216 | for (col = 0; col < pdata->matrix_key_cols; col++) { | 226 | for (col = 0; col < pdata->matrix_key_cols; col++) { |
217 | uint32_t bits_changed; | 227 | uint32_t bits_changed; |
228 | int code; | ||
218 | 229 | ||
219 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; | 230 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; |
220 | if (bits_changed == 0) | 231 | if (bits_changed == 0) |
@@ -224,12 +235,13 @@ scan: | |||
224 | if ((bits_changed & (1 << row)) == 0) | 235 | if ((bits_changed & (1 << row)) == 0) |
225 | continue; | 236 | continue; |
226 | 237 | ||
227 | input_report_key(keypad->input_dev, | 238 | code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); |
228 | lookup_matrix_keycode(keypad, row, col), | 239 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
229 | new_state[col] & (1 << row)); | 240 | input_report_key(input_dev, keypad->keycodes[code], |
241 | new_state[col] & (1 << row)); | ||
230 | } | 242 | } |
231 | } | 243 | } |
232 | input_sync(keypad->input_dev); | 244 | input_sync(input_dev); |
233 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); | 245 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); |
234 | } | 246 | } |
235 | 247 | ||
@@ -252,13 +264,15 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | |||
252 | if (delta == 0) | 264 | if (delta == 0) |
253 | return; | 265 | return; |
254 | 266 | ||
255 | if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) { | 267 | if (keypad->rotary_rel_code[r] == -1) { |
256 | int keycode = (delta > 0) ? keypad->rotary_up_key[r] : | 268 | int code = MAX_MATRIX_KEY_NUM + 2 * r + (delta > 0 ? 0 : 1); |
257 | keypad->rotary_down_key[r]; | 269 | unsigned char keycode = keypad->keycodes[code]; |
258 | 270 | ||
259 | /* simulate a press-n-release */ | 271 | /* simulate a press-n-release */ |
272 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
260 | input_report_key(dev, keycode, 1); | 273 | input_report_key(dev, keycode, 1); |
261 | input_sync(dev); | 274 | input_sync(dev); |
275 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
262 | input_report_key(dev, keycode, 0); | 276 | input_report_key(dev, keycode, 0); |
263 | input_sync(dev); | 277 | input_sync(dev); |
264 | } else { | 278 | } else { |
@@ -286,6 +300,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
286 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | 300 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) |
287 | { | 301 | { |
288 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 302 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
303 | struct input_dev *input_dev = keypad->input_dev; | ||
289 | unsigned int new_state; | 304 | unsigned int new_state; |
290 | uint32_t kpdk, bits_changed; | 305 | uint32_t kpdk, bits_changed; |
291 | int i; | 306 | int i; |
@@ -295,9 +310,6 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
295 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 310 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
296 | pxa27x_keypad_scan_rotary(keypad); | 311 | pxa27x_keypad_scan_rotary(keypad); |
297 | 312 | ||
298 | if (pdata->direct_key_map == NULL) | ||
299 | return; | ||
300 | |||
301 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | 313 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; |
302 | bits_changed = keypad->direct_key_state ^ new_state; | 314 | bits_changed = keypad->direct_key_state ^ new_state; |
303 | 315 | ||
@@ -305,12 +317,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
305 | return; | 317 | return; |
306 | 318 | ||
307 | for (i = 0; i < pdata->direct_key_num; i++) { | 319 | for (i = 0; i < pdata->direct_key_num; i++) { |
308 | if (bits_changed & (1 << i)) | 320 | if (bits_changed & (1 << i)) { |
309 | input_report_key(keypad->input_dev, | 321 | int code = MAX_MATRIX_KEY_NUM + i; |
310 | pdata->direct_key_map[i], | 322 | |
311 | (new_state & (1 << i))); | 323 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
324 | input_report_key(input_dev, keypad->keycodes[code], | ||
325 | new_state & (1 << i)); | ||
326 | } | ||
312 | } | 327 | } |
313 | input_sync(keypad->input_dev); | 328 | input_sync(input_dev); |
314 | keypad->direct_key_state = new_state; | 329 | keypad->direct_key_state = new_state; |
315 | } | 330 | } |
316 | 331 | ||
@@ -388,8 +403,9 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
388 | } | 403 | } |
389 | 404 | ||
390 | #ifdef CONFIG_PM | 405 | #ifdef CONFIG_PM |
391 | static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state) | 406 | static int pxa27x_keypad_suspend(struct device *dev) |
392 | { | 407 | { |
408 | struct platform_device *pdev = to_platform_device(dev); | ||
393 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 409 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
394 | 410 | ||
395 | clk_disable(keypad->clk); | 411 | clk_disable(keypad->clk); |
@@ -400,8 +416,9 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat | |||
400 | return 0; | 416 | return 0; |
401 | } | 417 | } |
402 | 418 | ||
403 | static int pxa27x_keypad_resume(struct platform_device *pdev) | 419 | static int pxa27x_keypad_resume(struct device *dev) |
404 | { | 420 | { |
421 | struct platform_device *pdev = to_platform_device(dev); | ||
405 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 422 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
406 | struct input_dev *input_dev = keypad->input_dev; | 423 | struct input_dev *input_dev = keypad->input_dev; |
407 | 424 | ||
@@ -420,55 +437,58 @@ static int pxa27x_keypad_resume(struct platform_device *pdev) | |||
420 | 437 | ||
421 | return 0; | 438 | return 0; |
422 | } | 439 | } |
423 | #else | ||
424 | #define pxa27x_keypad_suspend NULL | ||
425 | #define pxa27x_keypad_resume NULL | ||
426 | #endif | ||
427 | 440 | ||
428 | #define res_size(res) ((res)->end - (res)->start + 1) | 441 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { |
442 | .suspend = pxa27x_keypad_suspend, | ||
443 | .resume = pxa27x_keypad_resume, | ||
444 | }; | ||
445 | #endif | ||
429 | 446 | ||
430 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | 447 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) |
431 | { | 448 | { |
449 | struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; | ||
432 | struct pxa27x_keypad *keypad; | 450 | struct pxa27x_keypad *keypad; |
433 | struct input_dev *input_dev; | 451 | struct input_dev *input_dev; |
434 | struct resource *res; | 452 | struct resource *res; |
435 | int irq, error; | 453 | int irq, error; |
436 | 454 | ||
437 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | 455 | if (pdata == NULL) { |
438 | if (keypad == NULL) { | ||
439 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
440 | return -ENOMEM; | ||
441 | } | ||
442 | |||
443 | keypad->pdata = pdev->dev.platform_data; | ||
444 | if (keypad->pdata == NULL) { | ||
445 | dev_err(&pdev->dev, "no platform data defined\n"); | 456 | dev_err(&pdev->dev, "no platform data defined\n"); |
446 | error = -EINVAL; | 457 | return -EINVAL; |
447 | goto failed_free; | ||
448 | } | 458 | } |
449 | 459 | ||
450 | irq = platform_get_irq(pdev, 0); | 460 | irq = platform_get_irq(pdev, 0); |
451 | if (irq < 0) { | 461 | if (irq < 0) { |
452 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | 462 | dev_err(&pdev->dev, "failed to get keypad irq\n"); |
453 | error = -ENXIO; | 463 | return -ENXIO; |
454 | goto failed_free; | ||
455 | } | 464 | } |
456 | 465 | ||
457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 466 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
458 | if (res == NULL) { | 467 | if (res == NULL) { |
459 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | 468 | dev_err(&pdev->dev, "failed to get I/O memory\n"); |
460 | error = -ENXIO; | 469 | return -ENXIO; |
470 | } | ||
471 | |||
472 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | ||
473 | input_dev = input_allocate_device(); | ||
474 | if (!keypad || !input_dev) { | ||
475 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
476 | error = -ENOMEM; | ||
461 | goto failed_free; | 477 | goto failed_free; |
462 | } | 478 | } |
463 | 479 | ||
464 | res = request_mem_region(res->start, res_size(res), pdev->name); | 480 | keypad->pdata = pdata; |
481 | keypad->input_dev = input_dev; | ||
482 | keypad->irq = irq; | ||
483 | |||
484 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
465 | if (res == NULL) { | 485 | if (res == NULL) { |
466 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 486 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
467 | error = -EBUSY; | 487 | error = -EBUSY; |
468 | goto failed_free; | 488 | goto failed_free; |
469 | } | 489 | } |
470 | 490 | ||
471 | keypad->mmio_base = ioremap(res->start, res_size(res)); | 491 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
472 | if (keypad->mmio_base == NULL) { | 492 | if (keypad->mmio_base == NULL) { |
473 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 493 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
474 | error = -ENXIO; | 494 | error = -ENXIO; |
@@ -482,43 +502,35 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
482 | goto failed_free_io; | 502 | goto failed_free_io; |
483 | } | 503 | } |
484 | 504 | ||
485 | /* Create and register the input driver. */ | ||
486 | input_dev = input_allocate_device(); | ||
487 | if (!input_dev) { | ||
488 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
489 | error = -ENOMEM; | ||
490 | goto failed_put_clk; | ||
491 | } | ||
492 | |||
493 | input_dev->name = pdev->name; | 505 | input_dev->name = pdev->name; |
494 | input_dev->id.bustype = BUS_HOST; | 506 | input_dev->id.bustype = BUS_HOST; |
495 | input_dev->open = pxa27x_keypad_open; | 507 | input_dev->open = pxa27x_keypad_open; |
496 | input_dev->close = pxa27x_keypad_close; | 508 | input_dev->close = pxa27x_keypad_close; |
497 | input_dev->dev.parent = &pdev->dev; | 509 | input_dev->dev.parent = &pdev->dev; |
498 | 510 | ||
499 | keypad->input_dev = input_dev; | 511 | input_dev->keycode = keypad->keycodes; |
512 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
513 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
514 | |||
500 | input_set_drvdata(input_dev, keypad); | 515 | input_set_drvdata(input_dev, keypad); |
501 | 516 | ||
502 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 517 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
503 | if ((keypad->pdata->enable_rotary0 && | 518 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
504 | keypad->pdata->rotary0_rel_code) || | ||
505 | (keypad->pdata->enable_rotary1 && | ||
506 | keypad->pdata->rotary1_rel_code)) { | ||
507 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
508 | } | ||
509 | 519 | ||
510 | pxa27x_keypad_build_keycode(keypad); | 520 | pxa27x_keypad_build_keycode(keypad); |
511 | platform_set_drvdata(pdev, keypad); | 521 | |
522 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || | ||
523 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { | ||
524 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
525 | } | ||
512 | 526 | ||
513 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, | 527 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, |
514 | pdev->name, keypad); | 528 | pdev->name, keypad); |
515 | if (error) { | 529 | if (error) { |
516 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 530 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
517 | goto failed_free_dev; | 531 | goto failed_put_clk; |
518 | } | 532 | } |
519 | 533 | ||
520 | keypad->irq = irq; | ||
521 | |||
522 | /* Register the input device */ | 534 | /* Register the input device */ |
523 | error = input_register_device(input_dev); | 535 | error = input_register_device(input_dev); |
524 | if (error) { | 536 | if (error) { |
@@ -526,22 +538,21 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
526 | goto failed_free_irq; | 538 | goto failed_free_irq; |
527 | } | 539 | } |
528 | 540 | ||
541 | platform_set_drvdata(pdev, keypad); | ||
529 | device_init_wakeup(&pdev->dev, 1); | 542 | device_init_wakeup(&pdev->dev, 1); |
530 | 543 | ||
531 | return 0; | 544 | return 0; |
532 | 545 | ||
533 | failed_free_irq: | 546 | failed_free_irq: |
534 | free_irq(irq, pdev); | 547 | free_irq(irq, pdev); |
535 | platform_set_drvdata(pdev, NULL); | ||
536 | failed_free_dev: | ||
537 | input_free_device(input_dev); | ||
538 | failed_put_clk: | 548 | failed_put_clk: |
539 | clk_put(keypad->clk); | 549 | clk_put(keypad->clk); |
540 | failed_free_io: | 550 | failed_free_io: |
541 | iounmap(keypad->mmio_base); | 551 | iounmap(keypad->mmio_base); |
542 | failed_free_mem: | 552 | failed_free_mem: |
543 | release_mem_region(res->start, res_size(res)); | 553 | release_mem_region(res->start, resource_size(res)); |
544 | failed_free: | 554 | failed_free: |
555 | input_free_device(input_dev); | ||
545 | kfree(keypad); | 556 | kfree(keypad); |
546 | return error; | 557 | return error; |
547 | } | 558 | } |
@@ -552,8 +563,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
552 | struct resource *res; | 563 | struct resource *res; |
553 | 564 | ||
554 | free_irq(keypad->irq, pdev); | 565 | free_irq(keypad->irq, pdev); |
555 | |||
556 | clk_disable(keypad->clk); | ||
557 | clk_put(keypad->clk); | 566 | clk_put(keypad->clk); |
558 | 567 | ||
559 | input_unregister_device(keypad->input_dev); | 568 | input_unregister_device(keypad->input_dev); |
@@ -562,10 +571,11 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
562 | iounmap(keypad->mmio_base); | 571 | iounmap(keypad->mmio_base); |
563 | 572 | ||
564 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 573 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
565 | release_mem_region(res->start, res_size(res)); | 574 | release_mem_region(res->start, resource_size(res)); |
566 | 575 | ||
567 | platform_set_drvdata(pdev, NULL); | 576 | platform_set_drvdata(pdev, NULL); |
568 | kfree(keypad); | 577 | kfree(keypad); |
578 | |||
569 | return 0; | 579 | return 0; |
570 | } | 580 | } |
571 | 581 | ||
@@ -575,11 +585,12 @@ MODULE_ALIAS("platform:pxa27x-keypad"); | |||
575 | static struct platform_driver pxa27x_keypad_driver = { | 585 | static struct platform_driver pxa27x_keypad_driver = { |
576 | .probe = pxa27x_keypad_probe, | 586 | .probe = pxa27x_keypad_probe, |
577 | .remove = __devexit_p(pxa27x_keypad_remove), | 587 | .remove = __devexit_p(pxa27x_keypad_remove), |
578 | .suspend = pxa27x_keypad_suspend, | ||
579 | .resume = pxa27x_keypad_resume, | ||
580 | .driver = { | 588 | .driver = { |
581 | .name = "pxa27x-keypad", | 589 | .name = "pxa27x-keypad", |
582 | .owner = THIS_MODULE, | 590 | .owner = THIS_MODULE, |
591 | #ifdef CONFIG_PM | ||
592 | .pm = &pxa27x_keypad_pm_ops, | ||
593 | #endif | ||
583 | }, | 594 | }, |
584 | }; | 595 | }; |
585 | 596 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 68fd502fcfef..887af79b7bff 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -131,7 +131,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
131 | struct resource *res; | 131 | struct resource *res; |
132 | struct input_dev *input; | 132 | struct input_dev *input; |
133 | char clk_name[8]; | 133 | char clk_name[8]; |
134 | int i, k; | 134 | int i; |
135 | int irq, error; | 135 | int irq, error; |
136 | 136 | ||
137 | if (!pdev->dev.platform_data) { | 137 | if (!pdev->dev.platform_data) { |
@@ -198,17 +198,19 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
198 | input->id.product = 0x0001; | 198 | input->id.product = 0x0001; |
199 | input->id.version = 0x0100; | 199 | input->id.version = 0x0100; |
200 | 200 | ||
201 | input->keycode = pdata->keycodes; | ||
202 | input->keycodesize = sizeof(pdata->keycodes[0]); | ||
203 | input->keycodemax = ARRAY_SIZE(pdata->keycodes); | ||
204 | |||
201 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); | 205 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); |
202 | if (error) { | 206 | if (error) { |
203 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 207 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
204 | goto err4; | 208 | goto err4; |
205 | } | 209 | } |
206 | 210 | ||
207 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | 211 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) |
208 | k = pdata->keycodes[i]; | 212 | __set_bit(pdata->keycodes[i], input->keybit); |
209 | if (k) | 213 | __clear_bit(KEY_RESERVED, input->keybit); |
210 | input_set_capability(input, EV_KEY, k); | ||
211 | } | ||
212 | 214 | ||
213 | error = input_register_device(input); | 215 | error = input_register_device(input); |
214 | if (error) { | 216 | if (error) { |
@@ -224,7 +226,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
224 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | 226 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); |
225 | 227 | ||
226 | device_init_wakeup(&pdev->dev, 1); | 228 | device_init_wakeup(&pdev->dev, 1); |
229 | |||
227 | return 0; | 230 | return 0; |
231 | |||
228 | err5: | 232 | err5: |
229 | free_irq(irq, pdev); | 233 | free_irq(irq, pdev); |
230 | err4: | 234 | err4: |
@@ -255,6 +259,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) | |||
255 | 259 | ||
256 | platform_set_drvdata(pdev, NULL); | 260 | platform_set_drvdata(pdev, NULL); |
257 | kfree(priv); | 261 | kfree(priv); |
262 | |||
258 | return 0; | 263 | return 0; |
259 | } | 264 | } |
260 | 265 | ||
@@ -270,11 +275,12 @@ static int sh_keysc_suspend(struct device *dev) | |||
270 | if (device_may_wakeup(dev)) { | 275 | if (device_may_wakeup(dev)) { |
271 | value |= 0x80; | 276 | value |= 0x80; |
272 | enable_irq_wake(irq); | 277 | enable_irq_wake(irq); |
273 | } | 278 | } else { |
274 | else | ||
275 | value &= ~0x80; | 279 | value &= ~0x80; |
280 | } | ||
276 | 281 | ||
277 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); | 282 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); |
283 | |||
278 | return 0; | 284 | return 0; |
279 | } | 285 | } |
280 | 286 | ||
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 9fce6d1e29b2..472b56639cdb 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c | |||
@@ -73,7 +73,7 @@ static unsigned char sunkbd_keycode[128] = { | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | struct sunkbd { | 75 | struct sunkbd { |
76 | unsigned char keycode[128]; | 76 | unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)]; |
77 | struct input_dev *dev; | 77 | struct input_dev *dev; |
78 | struct serio *serio; | 78 | struct serio *serio; |
79 | struct work_struct tq; | 79 | struct work_struct tq; |
@@ -81,7 +81,7 @@ struct sunkbd { | |||
81 | char name[64]; | 81 | char name[64]; |
82 | char phys[32]; | 82 | char phys[32]; |
83 | char type; | 83 | char type; |
84 | unsigned char enabled; | 84 | bool enabled; |
85 | volatile s8 reset; | 85 | volatile s8 reset; |
86 | volatile s8 layout; | 86 | volatile s8 layout; |
87 | }; | 87 | }; |
@@ -94,10 +94,14 @@ struct sunkbd { | |||
94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, | 94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, |
95 | unsigned char data, unsigned int flags) | 95 | unsigned char data, unsigned int flags) |
96 | { | 96 | { |
97 | struct sunkbd* sunkbd = serio_get_drvdata(serio); | 97 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
98 | 98 | ||
99 | if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */ | 99 | if (sunkbd->reset <= -1) { |
100 | sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */ | 100 | /* |
101 | * If cp[i] is 0xff, sunkbd->reset will stay -1. | ||
102 | * The keyboard sends 0xff 0xff 0xID on powerup. | ||
103 | */ | ||
104 | sunkbd->reset = data; | ||
101 | wake_up_interruptible(&sunkbd->wait); | 105 | wake_up_interruptible(&sunkbd->wait); |
102 | goto out; | 106 | goto out; |
103 | } | 107 | } |
@@ -110,29 +114,33 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, | |||
110 | 114 | ||
111 | switch (data) { | 115 | switch (data) { |
112 | 116 | ||
113 | case SUNKBD_RET_RESET: | 117 | case SUNKBD_RET_RESET: |
114 | schedule_work(&sunkbd->tq); | 118 | schedule_work(&sunkbd->tq); |
115 | sunkbd->reset = -1; | 119 | sunkbd->reset = -1; |
116 | break; | 120 | break; |
117 | 121 | ||
118 | case SUNKBD_RET_LAYOUT: | 122 | case SUNKBD_RET_LAYOUT: |
119 | sunkbd->layout = -1; | 123 | sunkbd->layout = -1; |
120 | break; | 124 | break; |
125 | |||
126 | case SUNKBD_RET_ALLUP: /* All keys released */ | ||
127 | break; | ||
121 | 128 | ||
122 | case SUNKBD_RET_ALLUP: /* All keys released */ | 129 | default: |
130 | if (!sunkbd->enabled) | ||
123 | break; | 131 | break; |
124 | 132 | ||
125 | default: | 133 | if (sunkbd->keycode[data & SUNKBD_KEY]) { |
126 | if (!sunkbd->enabled) | 134 | input_report_key(sunkbd->dev, |
127 | break; | 135 | sunkbd->keycode[data & SUNKBD_KEY], |
128 | 136 | !(data & SUNKBD_RELEASE)); | |
129 | if (sunkbd->keycode[data & SUNKBD_KEY]) { | 137 | input_sync(sunkbd->dev); |
130 | input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); | 138 | } else { |
131 | input_sync(sunkbd->dev); | 139 | printk(KERN_WARNING |
132 | } else { | 140 | "sunkbd.c: Unknown key (scancode %#x) %s.\n", |
133 | printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", | 141 | data & SUNKBD_KEY, |
134 | data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); | 142 | data & SUNKBD_RELEASE ? "released" : "pressed"); |
135 | } | 143 | } |
136 | } | 144 | } |
137 | out: | 145 | out: |
138 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
@@ -142,34 +150,37 @@ out: | |||
142 | * sunkbd_event() handles events from the input module. | 150 | * sunkbd_event() handles events from the input module. |
143 | */ | 151 | */ |
144 | 152 | ||
145 | static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 153 | static int sunkbd_event(struct input_dev *dev, |
154 | unsigned int type, unsigned int code, int value) | ||
146 | { | 155 | { |
147 | struct sunkbd *sunkbd = input_get_drvdata(dev); | 156 | struct sunkbd *sunkbd = input_get_drvdata(dev); |
148 | 157 | ||
149 | switch (type) { | 158 | switch (type) { |
150 | 159 | ||
151 | case EV_LED: | 160 | case EV_LED: |
152 | 161 | ||
153 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 162 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
154 | sunkbd->serio->write(sunkbd->serio, | 163 | serio_write(sunkbd->serio, |
155 | (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | | 164 | (!!test_bit(LED_CAPSL, dev->led) << 3) | |
156 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); | 165 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | |
157 | return 0; | 166 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | |
167 | !!test_bit(LED_NUML, dev->led)); | ||
168 | return 0; | ||
158 | 169 | ||
159 | case EV_SND: | 170 | case EV_SND: |
160 | 171 | ||
161 | switch (code) { | 172 | switch (code) { |
162 | 173 | ||
163 | case SND_CLICK: | 174 | case SND_CLICK: |
164 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); | 175 | serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); |
165 | return 0; | 176 | return 0; |
166 | 177 | ||
167 | case SND_BELL: | 178 | case SND_BELL: |
168 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); | 179 | serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); |
169 | return 0; | 180 | return 0; |
170 | } | 181 | } |
171 | 182 | ||
172 | break; | 183 | break; |
173 | } | 184 | } |
174 | 185 | ||
175 | return -1; | 186 | return -1; |
@@ -183,7 +194,7 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
183 | static int sunkbd_initialize(struct sunkbd *sunkbd) | 194 | static int sunkbd_initialize(struct sunkbd *sunkbd) |
184 | { | 195 | { |
185 | sunkbd->reset = -2; | 196 | sunkbd->reset = -2; |
186 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); | 197 | serio_write(sunkbd->serio, SUNKBD_CMD_RESET); |
187 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 198 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
188 | if (sunkbd->reset < 0) | 199 | if (sunkbd->reset < 0) |
189 | return -1; | 200 | return -1; |
@@ -192,10 +203,13 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) | |||
192 | 203 | ||
193 | if (sunkbd->type == 4) { /* Type 4 keyboard */ | 204 | if (sunkbd->type == 4) { /* Type 4 keyboard */ |
194 | sunkbd->layout = -2; | 205 | sunkbd->layout = -2; |
195 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); | 206 | serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT); |
196 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); | 207 | wait_event_interruptible_timeout(sunkbd->wait, |
197 | if (sunkbd->layout < 0) return -1; | 208 | sunkbd->layout >= 0, HZ / 4); |
198 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; | 209 | if (sunkbd->layout < 0) |
210 | return -1; | ||
211 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) | ||
212 | sunkbd->type = 5; | ||
199 | } | 213 | } |
200 | 214 | ||
201 | return 0; | 215 | return 0; |
@@ -212,15 +226,19 @@ static void sunkbd_reinit(struct work_struct *work) | |||
212 | 226 | ||
213 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 227 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
214 | 228 | ||
215 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 229 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
216 | sunkbd->serio->write(sunkbd->serio, | 230 | serio_write(sunkbd->serio, |
217 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | | 231 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | |
218 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led)); | 232 | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | |
219 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | 233 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | |
220 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | 234 | !!test_bit(LED_NUML, sunkbd->dev->led)); |
235 | serio_write(sunkbd->serio, | ||
236 | SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | ||
237 | serio_write(sunkbd->serio, | ||
238 | SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | ||
221 | } | 239 | } |
222 | 240 | ||
223 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | 241 | static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) |
224 | { | 242 | { |
225 | serio_pause_rx(sunkbd->serio); | 243 | serio_pause_rx(sunkbd->serio); |
226 | sunkbd->enabled = enable; | 244 | sunkbd->enabled = enable; |
@@ -228,7 +246,8 @@ static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | |||
228 | } | 246 | } |
229 | 247 | ||
230 | /* | 248 | /* |
231 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures. | 249 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary |
250 | * structures. | ||
232 | */ | 251 | */ |
233 | 252 | ||
234 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | 253 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) |
@@ -260,7 +279,8 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
260 | goto fail3; | 279 | goto fail3; |
261 | } | 280 | } |
262 | 281 | ||
263 | snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); | 282 | snprintf(sunkbd->name, sizeof(sunkbd->name), |
283 | "Sun Type %d keyboard", sunkbd->type); | ||
264 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); | 284 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); |
265 | 285 | ||
266 | input_dev->name = sunkbd->name; | 286 | input_dev->name = sunkbd->name; |
@@ -284,11 +304,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
284 | input_dev->keycode = sunkbd->keycode; | 304 | input_dev->keycode = sunkbd->keycode; |
285 | input_dev->keycodesize = sizeof(unsigned char); | 305 | input_dev->keycodesize = sizeof(unsigned char); |
286 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); | 306 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); |
287 | for (i = 0; i < 128; i++) | 307 | for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++) |
288 | set_bit(sunkbd->keycode[i], input_dev->keybit); | 308 | __set_bit(sunkbd->keycode[i], input_dev->keybit); |
289 | clear_bit(0, input_dev->keybit); | 309 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
290 | 310 | ||
291 | sunkbd_enable(sunkbd, 1); | 311 | sunkbd_enable(sunkbd, true); |
292 | 312 | ||
293 | err = input_register_device(sunkbd->dev); | 313 | err = input_register_device(sunkbd->dev); |
294 | if (err) | 314 | if (err) |
@@ -296,7 +316,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
296 | 316 | ||
297 | return 0; | 317 | return 0; |
298 | 318 | ||
299 | fail4: sunkbd_enable(sunkbd, 0); | 319 | fail4: sunkbd_enable(sunkbd, false); |
300 | fail3: serio_close(serio); | 320 | fail3: serio_close(serio); |
301 | fail2: serio_set_drvdata(serio, NULL); | 321 | fail2: serio_set_drvdata(serio, NULL); |
302 | fail1: input_free_device(input_dev); | 322 | fail1: input_free_device(input_dev); |
@@ -312,7 +332,7 @@ static void sunkbd_disconnect(struct serio *serio) | |||
312 | { | 332 | { |
313 | struct sunkbd *sunkbd = serio_get_drvdata(serio); | 333 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
314 | 334 | ||
315 | sunkbd_enable(sunkbd, 0); | 335 | sunkbd_enable(sunkbd, false); |
316 | input_unregister_device(sunkbd->dev); | 336 | input_unregister_device(sunkbd->dev); |
317 | serio_close(serio); | 337 | serio_close(serio); |
318 | serio_set_drvdata(serio, NULL); | 338 | serio_set_drvdata(serio, NULL); |
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 677276b12020..42cb3faf7336 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #define KB_DISCHARGE_DELAY 10 | 31 | #define KB_DISCHARGE_DELAY 10 |
32 | #define KB_ACTIVATE_DELAY 10 | 32 | #define KB_ACTIVATE_DELAY 10 |
33 | 33 | ||
34 | static unsigned int tosakbd_keycode[NR_SCANCODES] = { | 34 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { |
35 | 0, | 35 | 0, |
36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | 36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, |
37 | 0, 0, 0, 0, 0, 0, 0, 0, | 37 | 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -50,9 +50,9 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct tosakbd { | 52 | struct tosakbd { |
53 | unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)]; | 53 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; |
54 | struct input_dev *input; | 54 | struct input_dev *input; |
55 | int suspended; | 55 | bool suspended; |
56 | spinlock_t lock; /* protect kbd scanning */ | 56 | spinlock_t lock; /* protect kbd scanning */ |
57 | struct timer_list timer; | 57 | struct timer_list timer; |
58 | }; | 58 | }; |
@@ -215,7 +215,7 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | |||
215 | unsigned long flags; | 215 | unsigned long flags; |
216 | 216 | ||
217 | spin_lock_irqsave(&tosakbd->lock, flags); | 217 | spin_lock_irqsave(&tosakbd->lock, flags); |
218 | tosakbd->suspended = 1; | 218 | tosakbd->suspended = true; |
219 | spin_unlock_irqrestore(&tosakbd->lock, flags); | 219 | spin_unlock_irqrestore(&tosakbd->lock, flags); |
220 | 220 | ||
221 | del_timer_sync(&tosakbd->timer); | 221 | del_timer_sync(&tosakbd->timer); |
@@ -227,7 +227,7 @@ static int tosakbd_resume(struct platform_device *dev) | |||
227 | { | 227 | { |
228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | 228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); |
229 | 229 | ||
230 | tosakbd->suspended = 0; | 230 | tosakbd->suspended = false; |
231 | tosakbd_scankeyboard(dev); | 231 | tosakbd_scankeyboard(dev); |
232 | 232 | ||
233 | return 0; | 233 | return 0; |
@@ -277,14 +277,14 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
277 | 277 | ||
278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
279 | input_dev->keycode = tosakbd->keycode; | 279 | input_dev->keycode = tosakbd->keycode; |
280 | input_dev->keycodesize = sizeof(unsigned int); | 280 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); |
281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | 281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); |
282 | 282 | ||
283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | 283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); |
284 | 284 | ||
285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | 285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) |
286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | 286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); |
287 | clear_bit(0, input_dev->keybit); | 287 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
288 | 288 | ||
289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | 289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ |
290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | 290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { |
@@ -344,7 +344,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
344 | " direction for GPIO %d, error %d\n", | 344 | " direction for GPIO %d, error %d\n", |
345 | gpio, error); | 345 | gpio, error); |
346 | gpio_free(gpio); | 346 | gpio_free(gpio); |
347 | goto fail; | 347 | goto fail2; |
348 | } | 348 | } |
349 | 349 | ||
350 | } | 350 | } |
@@ -353,7 +353,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
353 | if (error) { | 353 | if (error) { |
354 | printk(KERN_ERR "tosakbd: Unable to register input device, " | 354 | printk(KERN_ERR "tosakbd: Unable to register input device, " |
355 | "error: %d\n", error); | 355 | "error: %d\n", error); |
356 | goto fail; | 356 | goto fail2; |
357 | } | 357 | } |
358 | 358 | ||
359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | 359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c new file mode 100644 index 000000000000..9a2977c21696 --- /dev/null +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * twl4030_keypad.c - driver for 8x8 keypad controller in twl4030 chips | ||
3 | * | ||
4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Code re-written for 2430SDP by: | ||
8 | * Syed Mohammed Khasim <x0khasim@ti.com> | ||
9 | * | ||
10 | * Initial Code: | ||
11 | * Manjunatha G K <manjugk@ti.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/input.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/i2c/twl4030.h> | ||
35 | |||
36 | |||
37 | /* | ||
38 | * The TWL4030 family chips include a keypad controller that supports | ||
39 | * up to an 8x8 switch matrix. The controller can issue system wakeup | ||
40 | * events, since it uses only the always-on 32KiHz oscillator, and has | ||
41 | * an internal state machine that decodes pressed keys, including | ||
42 | * multi-key combinations. | ||
43 | * | ||
44 | * This driver lets boards define what keycodes they wish to report for | ||
45 | * which scancodes, as part of the "struct twl4030_keypad_data" used in | ||
46 | * the probe() routine. | ||
47 | * | ||
48 | * See the TPS65950 documentation; that's the general availability | ||
49 | * version of the TWL5030 second generation part. | ||
50 | */ | ||
51 | #define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */ | ||
52 | #define TWL4030_MAX_COLS 8 | ||
53 | #define TWL4030_ROW_SHIFT 3 | ||
54 | #define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS) | ||
55 | |||
56 | struct twl4030_keypad { | ||
57 | unsigned short keymap[TWL4030_KEYMAP_SIZE]; | ||
58 | u16 kp_state[TWL4030_MAX_ROWS]; | ||
59 | unsigned n_rows; | ||
60 | unsigned n_cols; | ||
61 | unsigned irq; | ||
62 | |||
63 | struct device *dbg_dev; | ||
64 | struct input_dev *input; | ||
65 | }; | ||
66 | |||
67 | /*----------------------------------------------------------------------*/ | ||
68 | |||
69 | /* arbitrary prescaler value 0..7 */ | ||
70 | #define PTV_PRESCALER 4 | ||
71 | |||
72 | /* Register Offsets */ | ||
73 | #define KEYP_CTRL 0x00 | ||
74 | #define KEYP_DEB 0x01 | ||
75 | #define KEYP_LONG_KEY 0x02 | ||
76 | #define KEYP_LK_PTV 0x03 | ||
77 | #define KEYP_TIMEOUT_L 0x04 | ||
78 | #define KEYP_TIMEOUT_H 0x05 | ||
79 | #define KEYP_KBC 0x06 | ||
80 | #define KEYP_KBR 0x07 | ||
81 | #define KEYP_SMS 0x08 | ||
82 | #define KEYP_FULL_CODE_7_0 0x09 /* row 0 column status */ | ||
83 | #define KEYP_FULL_CODE_15_8 0x0a /* ... row 1 ... */ | ||
84 | #define KEYP_FULL_CODE_23_16 0x0b | ||
85 | #define KEYP_FULL_CODE_31_24 0x0c | ||
86 | #define KEYP_FULL_CODE_39_32 0x0d | ||
87 | #define KEYP_FULL_CODE_47_40 0x0e | ||
88 | #define KEYP_FULL_CODE_55_48 0x0f | ||
89 | #define KEYP_FULL_CODE_63_56 0x10 | ||
90 | #define KEYP_ISR1 0x11 | ||
91 | #define KEYP_IMR1 0x12 | ||
92 | #define KEYP_ISR2 0x13 | ||
93 | #define KEYP_IMR2 0x14 | ||
94 | #define KEYP_SIR 0x15 | ||
95 | #define KEYP_EDR 0x16 /* edge triggers */ | ||
96 | #define KEYP_SIH_CTRL 0x17 | ||
97 | |||
98 | /* KEYP_CTRL_REG Fields */ | ||
99 | #define KEYP_CTRL_SOFT_NRST BIT(0) | ||
100 | #define KEYP_CTRL_SOFTMODEN BIT(1) | ||
101 | #define KEYP_CTRL_LK_EN BIT(2) | ||
102 | #define KEYP_CTRL_TOE_EN BIT(3) | ||
103 | #define KEYP_CTRL_TOLE_EN BIT(4) | ||
104 | #define KEYP_CTRL_RP_EN BIT(5) | ||
105 | #define KEYP_CTRL_KBD_ON BIT(6) | ||
106 | |||
107 | /* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/ | ||
108 | #define KEYP_PERIOD_US(t, prescale) ((t) / (31 << (prescale + 1)) - 1) | ||
109 | |||
110 | /* KEYP_LK_PTV_REG Fields */ | ||
111 | #define KEYP_LK_PTV_PTV_SHIFT 5 | ||
112 | |||
113 | /* KEYP_{IMR,ISR,SIR} Fields */ | ||
114 | #define KEYP_IMR1_MIS BIT(3) | ||
115 | #define KEYP_IMR1_TO BIT(2) | ||
116 | #define KEYP_IMR1_LK BIT(1) | ||
117 | #define KEYP_IMR1_KP BIT(0) | ||
118 | |||
119 | /* KEYP_EDR Fields */ | ||
120 | #define KEYP_EDR_KP_FALLING 0x01 | ||
121 | #define KEYP_EDR_KP_RISING 0x02 | ||
122 | #define KEYP_EDR_KP_BOTH 0x03 | ||
123 | #define KEYP_EDR_LK_FALLING 0x04 | ||
124 | #define KEYP_EDR_LK_RISING 0x08 | ||
125 | #define KEYP_EDR_TO_FALLING 0x10 | ||
126 | #define KEYP_EDR_TO_RISING 0x20 | ||
127 | #define KEYP_EDR_MIS_FALLING 0x40 | ||
128 | #define KEYP_EDR_MIS_RISING 0x80 | ||
129 | |||
130 | |||
131 | /*----------------------------------------------------------------------*/ | ||
132 | |||
133 | static int twl4030_kpread(struct twl4030_keypad *kp, | ||
134 | u8 *data, u32 reg, u8 num_bytes) | ||
135 | { | ||
136 | int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); | ||
137 | |||
138 | if (ret < 0) | ||
139 | dev_warn(kp->dbg_dev, | ||
140 | "Couldn't read TWL4030: %X - ret %d[%x]\n", | ||
141 | reg, ret, ret); | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) | ||
147 | { | ||
148 | int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); | ||
149 | |||
150 | if (ret < 0) | ||
151 | dev_warn(kp->dbg_dev, | ||
152 | "Could not write TWL4030: %X - ret %d[%x]\n", | ||
153 | reg, ret, ret); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static inline u16 twl4030_col_xlate(struct twl4030_keypad *kp, u8 col) | ||
159 | { | ||
160 | /* If all bits in a row are active for all coloumns then | ||
161 | * we have that row line connected to gnd. Mark this | ||
162 | * key on as if it was on matrix position n_cols (ie | ||
163 | * one higher than the size of the matrix). | ||
164 | */ | ||
165 | if (col == 0xFF) | ||
166 | return 1 << kp->n_cols; | ||
167 | else | ||
168 | return col & ((1 << kp->n_cols) - 1); | ||
169 | } | ||
170 | |||
171 | static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state) | ||
172 | { | ||
173 | u8 new_state[TWL4030_MAX_ROWS]; | ||
174 | int row; | ||
175 | int ret = twl4030_kpread(kp, new_state, | ||
176 | KEYP_FULL_CODE_7_0, kp->n_rows); | ||
177 | if (ret >= 0) | ||
178 | for (row = 0; row < kp->n_rows; row++) | ||
179 | state[row] = twl4030_col_xlate(kp, new_state[row]); | ||
180 | |||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) | ||
185 | { | ||
186 | int i; | ||
187 | u16 check = 0; | ||
188 | |||
189 | for (i = 0; i < kp->n_rows; i++) { | ||
190 | u16 col = key_state[i]; | ||
191 | |||
192 | if ((col & check) && hweight16(col) > 1) | ||
193 | return 1; | ||
194 | |||
195 | check |= col; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) | ||
202 | { | ||
203 | struct input_dev *input = kp->input; | ||
204 | u16 new_state[TWL4030_MAX_ROWS]; | ||
205 | int col, row; | ||
206 | |||
207 | if (release_all) | ||
208 | memset(new_state, 0, sizeof(new_state)); | ||
209 | else { | ||
210 | /* check for any changes */ | ||
211 | int ret = twl4030_read_kp_matrix_state(kp, new_state); | ||
212 | |||
213 | if (ret < 0) /* panic ... */ | ||
214 | return; | ||
215 | |||
216 | if (twl4030_is_in_ghost_state(kp, new_state)) | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | /* check for changes and print those */ | ||
221 | for (row = 0; row < kp->n_rows; row++) { | ||
222 | int changed = new_state[row] ^ kp->kp_state[row]; | ||
223 | |||
224 | if (!changed) | ||
225 | continue; | ||
226 | |||
227 | for (col = 0; col < kp->n_cols; col++) { | ||
228 | int code; | ||
229 | |||
230 | if (!(changed & (1 << col))) | ||
231 | continue; | ||
232 | |||
233 | dev_dbg(kp->dbg_dev, "key [%d:%d] %s\n", row, col, | ||
234 | (new_state[row] & (1 << col)) ? | ||
235 | "press" : "release"); | ||
236 | |||
237 | code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT); | ||
238 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
239 | input_report_key(input, kp->keymap[code], | ||
240 | new_state[row] & (1 << col)); | ||
241 | } | ||
242 | kp->kp_state[row] = new_state[row]; | ||
243 | } | ||
244 | input_sync(input); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Keypad interrupt handler | ||
249 | */ | ||
250 | static irqreturn_t do_kp_irq(int irq, void *_kp) | ||
251 | { | ||
252 | struct twl4030_keypad *kp = _kp; | ||
253 | u8 reg; | ||
254 | int ret; | ||
255 | |||
256 | #ifdef CONFIG_LOCKDEP | ||
257 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
258 | * we don't want and can't tolerate. Although it might be | ||
259 | * friendlier not to borrow this thread context... | ||
260 | */ | ||
261 | local_irq_enable(); | ||
262 | #endif | ||
263 | |||
264 | /* Read & Clear TWL4030 pending interrupt */ | ||
265 | ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); | ||
266 | |||
267 | /* Release all keys if I2C has gone bad or | ||
268 | * the KEYP has gone to idle state */ | ||
269 | if (ret >= 0 && (reg & KEYP_IMR1_KP)) | ||
270 | twl4030_kp_scan(kp, false); | ||
271 | else | ||
272 | twl4030_kp_scan(kp, true); | ||
273 | |||
274 | return IRQ_HANDLED; | ||
275 | } | ||
276 | |||
277 | static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) | ||
278 | { | ||
279 | u8 reg; | ||
280 | int i; | ||
281 | |||
282 | /* Enable controller, with hardware decoding but not autorepeat */ | ||
283 | reg = KEYP_CTRL_SOFT_NRST | KEYP_CTRL_SOFTMODEN | ||
284 | | KEYP_CTRL_TOE_EN | KEYP_CTRL_KBD_ON; | ||
285 | if (twl4030_kpwrite_u8(kp, reg, KEYP_CTRL) < 0) | ||
286 | return -EIO; | ||
287 | |||
288 | /* NOTE: we could use sih_setup() here to package keypad | ||
289 | * event sources as four different IRQs ... but we don't. | ||
290 | */ | ||
291 | |||
292 | /* Enable TO rising and KP rising and falling edge detection */ | ||
293 | reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING; | ||
294 | if (twl4030_kpwrite_u8(kp, reg, KEYP_EDR) < 0) | ||
295 | return -EIO; | ||
296 | |||
297 | /* Set PTV prescaler Field */ | ||
298 | reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT); | ||
299 | if (twl4030_kpwrite_u8(kp, reg, KEYP_LK_PTV) < 0) | ||
300 | return -EIO; | ||
301 | |||
302 | /* Set key debounce time to 20 ms */ | ||
303 | i = KEYP_PERIOD_US(20000, PTV_PRESCALER); | ||
304 | if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0) | ||
305 | return -EIO; | ||
306 | |||
307 | /* Set timeout period to 100 ms */ | ||
308 | i = KEYP_PERIOD_US(200000, PTV_PRESCALER); | ||
309 | if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0) | ||
310 | return -EIO; | ||
311 | |||
312 | if (twl4030_kpwrite_u8(kp, (i >> 8), KEYP_TIMEOUT_H) < 0) | ||
313 | return -EIO; | ||
314 | |||
315 | /* | ||
316 | * Enable Clear-on-Read; disable remembering events that fire | ||
317 | * after the IRQ but before our handler acks (reads) them, | ||
318 | */ | ||
319 | reg = TWL4030_SIH_CTRL_COR_MASK | TWL4030_SIH_CTRL_PENDDIS_MASK; | ||
320 | if (twl4030_kpwrite_u8(kp, reg, KEYP_SIH_CTRL) < 0) | ||
321 | return -EIO; | ||
322 | |||
323 | /* initialize key state; irqs update it from here on */ | ||
324 | if (twl4030_read_kp_matrix_state(kp, kp->kp_state) < 0) | ||
325 | return -EIO; | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Registers keypad device with input subsystem | ||
332 | * and configures TWL4030 keypad registers | ||
333 | */ | ||
334 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) | ||
335 | { | ||
336 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; | ||
337 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
338 | struct twl4030_keypad *kp; | ||
339 | struct input_dev *input; | ||
340 | u8 reg; | ||
341 | int error; | ||
342 | |||
343 | if (!pdata || !pdata->rows || !pdata->cols || | ||
344 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { | ||
345 | dev_err(&pdev->dev, "Invalid platform_data\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | ||
350 | input = input_allocate_device(); | ||
351 | if (!kp || !input) { | ||
352 | error = -ENOMEM; | ||
353 | goto err1; | ||
354 | } | ||
355 | |||
356 | /* Get the debug Device */ | ||
357 | kp->dbg_dev = &pdev->dev; | ||
358 | kp->input = input; | ||
359 | |||
360 | kp->n_rows = pdata->rows; | ||
361 | kp->n_cols = pdata->cols; | ||
362 | kp->irq = platform_get_irq(pdev, 0); | ||
363 | |||
364 | /* setup input device */ | ||
365 | __set_bit(EV_KEY, input->evbit); | ||
366 | |||
367 | /* Enable auto repeat feature of Linux input subsystem */ | ||
368 | if (pdata->rep) | ||
369 | __set_bit(EV_REP, input->evbit); | ||
370 | |||
371 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
372 | |||
373 | input->name = "TWL4030 Keypad"; | ||
374 | input->phys = "twl4030_keypad/input0"; | ||
375 | input->dev.parent = &pdev->dev; | ||
376 | |||
377 | input->id.bustype = BUS_HOST; | ||
378 | input->id.vendor = 0x0001; | ||
379 | input->id.product = 0x0001; | ||
380 | input->id.version = 0x0003; | ||
381 | |||
382 | input->keycode = kp->keymap; | ||
383 | input->keycodesize = sizeof(kp->keymap[0]); | ||
384 | input->keycodemax = ARRAY_SIZE(kp->keymap); | ||
385 | |||
386 | matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT, | ||
387 | input->keycode, input->keybit); | ||
388 | |||
389 | error = input_register_device(input); | ||
390 | if (error) { | ||
391 | dev_err(kp->dbg_dev, | ||
392 | "Unable to register twl4030 keypad device\n"); | ||
393 | goto err1; | ||
394 | } | ||
395 | |||
396 | error = twl4030_kp_program(kp); | ||
397 | if (error) | ||
398 | goto err2; | ||
399 | |||
400 | /* | ||
401 | * This ISR will always execute in kernel thread context because of | ||
402 | * the need to access the TWL4030 over the I2C bus. | ||
403 | * | ||
404 | * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... | ||
405 | */ | ||
406 | error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); | ||
407 | if (error) { | ||
408 | dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", | ||
409 | kp->irq); | ||
410 | goto err3; | ||
411 | } | ||
412 | |||
413 | /* Enable KP and TO interrupts now. */ | ||
414 | reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO); | ||
415 | if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) { | ||
416 | error = -EIO; | ||
417 | goto err4; | ||
418 | } | ||
419 | |||
420 | platform_set_drvdata(pdev, kp); | ||
421 | return 0; | ||
422 | |||
423 | err4: | ||
424 | /* mask all events - we don't care about the result */ | ||
425 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); | ||
426 | err3: | ||
427 | free_irq(kp->irq, NULL); | ||
428 | err2: | ||
429 | input_unregister_device(input); | ||
430 | input = NULL; | ||
431 | err1: | ||
432 | input_free_device(input); | ||
433 | kfree(kp); | ||
434 | return error; | ||
435 | } | ||
436 | |||
437 | static int __devexit twl4030_kp_remove(struct platform_device *pdev) | ||
438 | { | ||
439 | struct twl4030_keypad *kp = platform_get_drvdata(pdev); | ||
440 | |||
441 | free_irq(kp->irq, kp); | ||
442 | input_unregister_device(kp->input); | ||
443 | platform_set_drvdata(pdev, NULL); | ||
444 | kfree(kp); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * NOTE: twl4030 are multi-function devices connected via I2C. | ||
451 | * So this device is a child of an I2C parent, thus it needs to | ||
452 | * support unplug/replug (which most platform devices don't). | ||
453 | */ | ||
454 | |||
455 | static struct platform_driver twl4030_kp_driver = { | ||
456 | .probe = twl4030_kp_probe, | ||
457 | .remove = __devexit_p(twl4030_kp_remove), | ||
458 | .driver = { | ||
459 | .name = "twl4030_keypad", | ||
460 | .owner = THIS_MODULE, | ||
461 | }, | ||
462 | }; | ||
463 | |||
464 | static int __init twl4030_kp_init(void) | ||
465 | { | ||
466 | return platform_driver_register(&twl4030_kp_driver); | ||
467 | } | ||
468 | module_init(twl4030_kp_init); | ||
469 | |||
470 | static void __exit twl4030_kp_exit(void) | ||
471 | { | ||
472 | platform_driver_unregister(&twl4030_kp_driver); | ||
473 | } | ||
474 | module_exit(twl4030_kp_exit); | ||
475 | |||
476 | MODULE_AUTHOR("Texas Instruments"); | ||
477 | MODULE_DESCRIPTION("TWL4030 Keypad Driver"); | ||
478 | MODULE_LICENSE("GPL"); | ||
479 | MODULE_ALIAS("platform:twl4030_keypad"); | ||
480 | |||
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c new file mode 100644 index 000000000000..6032def03707 --- /dev/null +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@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;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <mach/w90p910_keypad.h> | ||
24 | |||
25 | /* Keypad Interface Control Registers */ | ||
26 | #define KPI_CONF 0x00 | ||
27 | #define KPI_3KCONF 0x04 | ||
28 | #define KPI_LPCONF 0x08 | ||
29 | #define KPI_STATUS 0x0C | ||
30 | |||
31 | #define IS1KEY (0x01 << 16) | ||
32 | #define INTTR (0x01 << 21) | ||
33 | #define KEY0R (0x0f << 3) | ||
34 | #define KEY0C 0x07 | ||
35 | #define DEBOUNCE_BIT 0x08 | ||
36 | #define KSIZE0 (0x01 << 16) | ||
37 | #define KSIZE1 (0x01 << 17) | ||
38 | #define KPSEL (0x01 << 19) | ||
39 | #define ENKP (0x01 << 18) | ||
40 | |||
41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | ||
42 | #define KGET_COLUMN(n) ((n) & KEY0C) | ||
43 | |||
44 | #define W90P910_MAX_KEY_NUM (8 * 8) | ||
45 | #define W90P910_ROW_SHIFT 3 | ||
46 | |||
47 | struct w90p910_keypad { | ||
48 | const struct w90p910_keypad_platform_data *pdata; | ||
49 | struct clk *clk; | ||
50 | struct input_dev *input_dev; | ||
51 | void __iomem *mmio_base; | ||
52 | int irq; | ||
53 | unsigned short keymap[W90P910_MAX_KEY_NUM]; | ||
54 | }; | ||
55 | |||
56 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | ||
57 | unsigned int status) | ||
58 | { | ||
59 | struct input_dev *input_dev = keypad->input_dev; | ||
60 | unsigned int row = KGET_RAW(status); | ||
61 | unsigned int col = KGET_COLUMN(status); | ||
62 | unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); | ||
63 | unsigned int key = keypad->keymap[code]; | ||
64 | |||
65 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
66 | input_report_key(input_dev, key, 1); | ||
67 | input_sync(input_dev); | ||
68 | |||
69 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
70 | input_report_key(input_dev, key, 0); | ||
71 | input_sync(input_dev); | ||
72 | } | ||
73 | |||
74 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | ||
75 | { | ||
76 | struct w90p910_keypad *keypad = dev_id; | ||
77 | unsigned int kstatus, val; | ||
78 | |||
79 | kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); | ||
80 | |||
81 | val = INTTR | IS1KEY; | ||
82 | |||
83 | if (kstatus & val) | ||
84 | w90p910_keypad_scan_matrix(keypad, kstatus); | ||
85 | |||
86 | return IRQ_HANDLED; | ||
87 | } | ||
88 | |||
89 | static int w90p910_keypad_open(struct input_dev *dev) | ||
90 | { | ||
91 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
92 | const struct w90p910_keypad_platform_data *pdata = keypad->pdata; | ||
93 | unsigned int val, config; | ||
94 | |||
95 | /* Enable unit clock */ | ||
96 | clk_enable(keypad->clk); | ||
97 | |||
98 | val = __raw_readl(keypad->mmio_base + KPI_CONF); | ||
99 | val |= (KPSEL | ENKP); | ||
100 | val &= ~(KSIZE0 | KSIZE1); | ||
101 | |||
102 | config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); | ||
103 | |||
104 | val |= config; | ||
105 | |||
106 | __raw_writel(val, keypad->mmio_base + KPI_CONF); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void w90p910_keypad_close(struct input_dev *dev) | ||
112 | { | ||
113 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
114 | |||
115 | /* Disable clock unit */ | ||
116 | clk_disable(keypad->clk); | ||
117 | } | ||
118 | |||
119 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | ||
120 | { | ||
121 | const struct w90p910_keypad_platform_data *pdata = | ||
122 | pdev->dev.platform_data; | ||
123 | const struct matrix_keymap_data *keymap_data; | ||
124 | struct w90p910_keypad *keypad; | ||
125 | struct input_dev *input_dev; | ||
126 | struct resource *res; | ||
127 | int irq; | ||
128 | int error; | ||
129 | |||
130 | if (!pdata) { | ||
131 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | keymap_data = pdata->keymap_data; | ||
136 | |||
137 | irq = platform_get_irq(pdev, 0); | ||
138 | if (irq < 0) { | ||
139 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
140 | return -ENXIO; | ||
141 | } | ||
142 | |||
143 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | ||
144 | input_dev = input_allocate_device(); | ||
145 | if (!keypad || !input_dev) { | ||
146 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
147 | error = -ENOMEM; | ||
148 | goto failed_free; | ||
149 | } | ||
150 | |||
151 | keypad->pdata = pdata; | ||
152 | keypad->input_dev = input_dev; | ||
153 | keypad->irq = irq; | ||
154 | |||
155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
156 | if (res == NULL) { | ||
157 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
158 | error = -ENXIO; | ||
159 | goto failed_free; | ||
160 | } | ||
161 | |||
162 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
163 | if (res == NULL) { | ||
164 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
165 | error = -EBUSY; | ||
166 | goto failed_free; | ||
167 | } | ||
168 | |||
169 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
170 | if (keypad->mmio_base == NULL) { | ||
171 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
172 | error = -ENXIO; | ||
173 | goto failed_free_res; | ||
174 | } | ||
175 | |||
176 | keypad->clk = clk_get(&pdev->dev, NULL); | ||
177 | if (IS_ERR(keypad->clk)) { | ||
178 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
179 | error = PTR_ERR(keypad->clk); | ||
180 | goto failed_free_io; | ||
181 | } | ||
182 | |||
183 | /* set multi-function pin for w90p910 kpi. */ | ||
184 | mfp_set_groupi(&pdev->dev); | ||
185 | |||
186 | input_dev->name = pdev->name; | ||
187 | input_dev->id.bustype = BUS_HOST; | ||
188 | input_dev->open = w90p910_keypad_open; | ||
189 | input_dev->close = w90p910_keypad_close; | ||
190 | input_dev->dev.parent = &pdev->dev; | ||
191 | |||
192 | input_dev->keycode = keypad->keymap; | ||
193 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | ||
194 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
195 | |||
196 | input_set_drvdata(input_dev, keypad); | ||
197 | |||
198 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
199 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
200 | |||
201 | matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT, | ||
202 | input_dev->keycode, input_dev->keybit); | ||
203 | |||
204 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | ||
205 | IRQF_DISABLED, pdev->name, keypad); | ||
206 | if (error) { | ||
207 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
208 | goto failed_put_clk; | ||
209 | } | ||
210 | |||
211 | /* Register the input device */ | ||
212 | error = input_register_device(input_dev); | ||
213 | if (error) { | ||
214 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
215 | goto failed_free_irq; | ||
216 | } | ||
217 | |||
218 | platform_set_drvdata(pdev, keypad); | ||
219 | return 0; | ||
220 | |||
221 | failed_free_irq: | ||
222 | free_irq(irq, pdev); | ||
223 | failed_put_clk: | ||
224 | clk_put(keypad->clk); | ||
225 | failed_free_io: | ||
226 | iounmap(keypad->mmio_base); | ||
227 | failed_free_res: | ||
228 | release_mem_region(res->start, resource_size(res)); | ||
229 | failed_free: | ||
230 | input_free_device(input_dev); | ||
231 | kfree(keypad); | ||
232 | return error; | ||
233 | } | ||
234 | |||
235 | static int __devexit w90p910_keypad_remove(struct platform_device *pdev) | ||
236 | { | ||
237 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | ||
238 | struct resource *res; | ||
239 | |||
240 | free_irq(keypad->irq, pdev); | ||
241 | |||
242 | clk_put(keypad->clk); | ||
243 | |||
244 | input_unregister_device(keypad->input_dev); | ||
245 | |||
246 | iounmap(keypad->mmio_base); | ||
247 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
248 | release_mem_region(res->start, resource_size(res)); | ||
249 | |||
250 | platform_set_drvdata(pdev, NULL); | ||
251 | kfree(keypad); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static struct platform_driver w90p910_keypad_driver = { | ||
257 | .probe = w90p910_keypad_probe, | ||
258 | .remove = __devexit_p(w90p910_keypad_remove), | ||
259 | .driver = { | ||
260 | .name = "nuc900-keypad", | ||
261 | .owner = THIS_MODULE, | ||
262 | }, | ||
263 | }; | ||
264 | |||
265 | static int __init w90p910_keypad_init(void) | ||
266 | { | ||
267 | return platform_driver_register(&w90p910_keypad_driver); | ||
268 | } | ||
269 | |||
270 | static void __exit w90p910_keypad_exit(void) | ||
271 | { | ||
272 | platform_driver_unregister(&w90p910_keypad_driver); | ||
273 | } | ||
274 | |||
275 | module_init(w90p910_keypad_init); | ||
276 | module_exit(w90p910_keypad_exit); | ||
277 | |||
278 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
279 | MODULE_DESCRIPTION("w90p910 keypad driver"); | ||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_ALIAS("platform:nuc900-keypad"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1acfa3a05aad..cbe21bc96b52 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -269,4 +269,14 @@ config INPUT_DM355EVM | |||
269 | 269 | ||
270 | To compile this driver as a module, choose M here: the | 270 | To compile this driver as a module, choose M here: the |
271 | module will be called dm355evm_keys. | 271 | module will be called dm355evm_keys. |
272 | |||
273 | config INPUT_BFIN_ROTARY | ||
274 | tristate "Blackfin Rotary support" | ||
275 | depends on BF54x || BF52x | ||
276 | help | ||
277 | Say Y here if you want to use the Blackfin Rotary. | ||
278 | |||
279 | To compile this driver as a module, choose M here: the | ||
280 | module will be called bfin-rotary. | ||
281 | |||
272 | endif | 282 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0d979fd4cd57..79c1e9a5ea31 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT_APANEL) += apanel.o | |||
8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
11 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | ||
11 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 12 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 13 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
13 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 14 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c new file mode 100644 index 000000000000..690f3fafa03b --- /dev/null +++ b/drivers/input/misc/bfin_rotary.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * Rotary counter driver for Analog Devices Blackfin Processors | ||
3 | * | ||
4 | * Copyright 2008-2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/input.h> | ||
16 | |||
17 | #include <asm/portmux.h> | ||
18 | #include <asm/bfin_rotary.h> | ||
19 | |||
20 | static const u16 per_cnt[] = { | ||
21 | P_CNT_CUD, | ||
22 | P_CNT_CDG, | ||
23 | P_CNT_CZM, | ||
24 | 0 | ||
25 | }; | ||
26 | |||
27 | struct bfin_rot { | ||
28 | struct input_dev *input; | ||
29 | int irq; | ||
30 | unsigned int up_key; | ||
31 | unsigned int down_key; | ||
32 | unsigned int button_key; | ||
33 | unsigned int rel_code; | ||
34 | unsigned short cnt_config; | ||
35 | unsigned short cnt_imask; | ||
36 | unsigned short cnt_debounce; | ||
37 | }; | ||
38 | |||
39 | static void report_key_event(struct input_dev *input, int keycode) | ||
40 | { | ||
41 | /* simulate a press-n-release */ | ||
42 | input_report_key(input, keycode, 1); | ||
43 | input_sync(input); | ||
44 | input_report_key(input, keycode, 0); | ||
45 | input_sync(input); | ||
46 | } | ||
47 | |||
48 | static void report_rotary_event(struct bfin_rot *rotary, int delta) | ||
49 | { | ||
50 | struct input_dev *input = rotary->input; | ||
51 | |||
52 | if (rotary->up_key) { | ||
53 | report_key_event(input, | ||
54 | delta > 0 ? rotary->up_key : rotary->down_key); | ||
55 | } else { | ||
56 | input_report_rel(input, rotary->rel_code, delta); | ||
57 | input_sync(input); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) | ||
62 | { | ||
63 | struct platform_device *pdev = dev_id; | ||
64 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
65 | int delta; | ||
66 | |||
67 | switch (bfin_read_CNT_STATUS()) { | ||
68 | |||
69 | case ICII: | ||
70 | break; | ||
71 | |||
72 | case UCII: | ||
73 | case DCII: | ||
74 | delta = bfin_read_CNT_COUNTER(); | ||
75 | if (delta) | ||
76 | report_rotary_event(rotary, delta); | ||
77 | break; | ||
78 | |||
79 | case CZMII: | ||
80 | report_key_event(rotary->input, rotary->button_key); | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | bfin_write_CNT_COMMAND(W1LCNT_ZERO); /* Clear COUNTER */ | ||
88 | bfin_write_CNT_STATUS(-1); /* Clear STATUS */ | ||
89 | |||
90 | return IRQ_HANDLED; | ||
91 | } | ||
92 | |||
93 | static int __devinit bfin_rotary_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; | ||
96 | struct bfin_rot *rotary; | ||
97 | struct input_dev *input; | ||
98 | int error; | ||
99 | |||
100 | /* Basic validation */ | ||
101 | if ((pdata->rotary_up_key && !pdata->rotary_down_key) || | ||
102 | (!pdata->rotary_up_key && pdata->rotary_down_key)) { | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | error = peripheral_request_list(per_cnt, dev_name(&pdev->dev)); | ||
107 | if (error) { | ||
108 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | rotary = kzalloc(sizeof(struct bfin_rot), GFP_KERNEL); | ||
113 | input = input_allocate_device(); | ||
114 | if (!rotary || !input) { | ||
115 | error = -ENOMEM; | ||
116 | goto out1; | ||
117 | } | ||
118 | |||
119 | rotary->input = input; | ||
120 | |||
121 | rotary->up_key = pdata->rotary_up_key; | ||
122 | rotary->down_key = pdata->rotary_down_key; | ||
123 | rotary->button_key = pdata->rotary_button_key; | ||
124 | rotary->rel_code = pdata->rotary_rel_code; | ||
125 | |||
126 | error = rotary->irq = platform_get_irq(pdev, 0); | ||
127 | if (error < 0) | ||
128 | goto out1; | ||
129 | |||
130 | input->name = pdev->name; | ||
131 | input->phys = "bfin-rotary/input0"; | ||
132 | input->dev.parent = &pdev->dev; | ||
133 | |||
134 | input_set_drvdata(input, rotary); | ||
135 | |||
136 | input->id.bustype = BUS_HOST; | ||
137 | input->id.vendor = 0x0001; | ||
138 | input->id.product = 0x0001; | ||
139 | input->id.version = 0x0100; | ||
140 | |||
141 | if (rotary->up_key) { | ||
142 | __set_bit(EV_KEY, input->evbit); | ||
143 | __set_bit(rotary->up_key, input->keybit); | ||
144 | __set_bit(rotary->down_key, input->keybit); | ||
145 | } else { | ||
146 | __set_bit(EV_REL, input->evbit); | ||
147 | __set_bit(rotary->rel_code, input->relbit); | ||
148 | } | ||
149 | |||
150 | if (rotary->button_key) { | ||
151 | __set_bit(EV_KEY, input->evbit); | ||
152 | __set_bit(rotary->button_key, input->keybit); | ||
153 | } | ||
154 | |||
155 | error = request_irq(rotary->irq, bfin_rotary_isr, | ||
156 | 0, dev_name(&pdev->dev), pdev); | ||
157 | if (error) { | ||
158 | dev_err(&pdev->dev, | ||
159 | "unable to claim irq %d; error %d\n", | ||
160 | rotary->irq, error); | ||
161 | goto out1; | ||
162 | } | ||
163 | |||
164 | error = input_register_device(input); | ||
165 | if (error) { | ||
166 | dev_err(&pdev->dev, | ||
167 | "unable to register input device (%d)\n", error); | ||
168 | goto out2; | ||
169 | } | ||
170 | |||
171 | if (pdata->rotary_button_key) | ||
172 | bfin_write_CNT_IMASK(CZMIE); | ||
173 | |||
174 | if (pdata->mode & ROT_DEBE) | ||
175 | bfin_write_CNT_DEBOUNCE(pdata->debounce & DPRESCALE); | ||
176 | |||
177 | if (pdata->mode) | ||
178 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | | ||
179 | (pdata->mode & ~CNTE)); | ||
180 | |||
181 | bfin_write_CNT_IMASK(bfin_read_CNT_IMASK() | UCIE | DCIE); | ||
182 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | CNTE); | ||
183 | |||
184 | platform_set_drvdata(pdev, rotary); | ||
185 | device_init_wakeup(&pdev->dev, 1); | ||
186 | |||
187 | return 0; | ||
188 | |||
189 | out2: | ||
190 | free_irq(rotary->irq, pdev); | ||
191 | out1: | ||
192 | input_free_device(input); | ||
193 | kfree(rotary); | ||
194 | peripheral_free_list(per_cnt); | ||
195 | |||
196 | return error; | ||
197 | } | ||
198 | |||
199 | static int __devexit bfin_rotary_remove(struct platform_device *pdev) | ||
200 | { | ||
201 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
202 | |||
203 | bfin_write_CNT_CONFIG(0); | ||
204 | bfin_write_CNT_IMASK(0); | ||
205 | |||
206 | free_irq(rotary->irq, pdev); | ||
207 | input_unregister_device(rotary->input); | ||
208 | peripheral_free_list(per_cnt); | ||
209 | |||
210 | kfree(rotary); | ||
211 | platform_set_drvdata(pdev, NULL); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | #ifdef CONFIG_PM | ||
217 | static int bfin_rotary_suspend(struct device *dev) | ||
218 | { | ||
219 | struct platform_device *pdev = to_platform_device(dev); | ||
220 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
221 | |||
222 | rotary->cnt_config = bfin_read_CNT_CONFIG(); | ||
223 | rotary->cnt_imask = bfin_read_CNT_IMASK(); | ||
224 | rotary->cnt_debounce = bfin_read_CNT_DEBOUNCE(); | ||
225 | |||
226 | if (device_may_wakeup(&pdev->dev)) | ||
227 | enable_irq_wake(rotary->irq); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int bfin_rotary_resume(struct device *dev) | ||
233 | { | ||
234 | struct platform_device *pdev = to_platform_device(dev); | ||
235 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
236 | |||
237 | bfin_write_CNT_DEBOUNCE(rotary->cnt_debounce); | ||
238 | bfin_write_CNT_IMASK(rotary->cnt_imask); | ||
239 | bfin_write_CNT_CONFIG(rotary->cnt_config & ~CNTE); | ||
240 | |||
241 | if (device_may_wakeup(&pdev->dev)) | ||
242 | disable_irq_wake(rotary->irq); | ||
243 | |||
244 | if (rotary->cnt_config & CNTE) | ||
245 | bfin_write_CNT_CONFIG(rotary->cnt_config); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | ||
251 | .suspend = bfin_rotary_suspend, | ||
252 | .resume = bfin_rotary_resume, | ||
253 | }; | ||
254 | #endif | ||
255 | |||
256 | static struct platform_driver bfin_rotary_device_driver = { | ||
257 | .probe = bfin_rotary_probe, | ||
258 | .remove = __devexit_p(bfin_rotary_remove), | ||
259 | .driver = { | ||
260 | .name = "bfin-rotary", | ||
261 | .owner = THIS_MODULE, | ||
262 | #ifdef CONFIG_PM | ||
263 | .pm = &bfin_rotary_pm_ops, | ||
264 | #endif | ||
265 | }, | ||
266 | }; | ||
267 | |||
268 | static int __init bfin_rotary_init(void) | ||
269 | { | ||
270 | return platform_driver_register(&bfin_rotary_device_driver); | ||
271 | } | ||
272 | module_init(bfin_rotary_init); | ||
273 | |||
274 | static void __exit bfin_rotary_exit(void) | ||
275 | { | ||
276 | platform_driver_unregister(&bfin_rotary_device_driver); | ||
277 | } | ||
278 | module_exit(bfin_rotary_exit); | ||
279 | |||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
282 | MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); | ||
283 | MODULE_ALIAS("platform:bfin-rotary"); | ||
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index d114d3a9e1e9..ee73d7219c92 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -116,7 +116,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | bdev->poll_dev = poll_dev; | 118 | bdev->poll_dev = poll_dev; |
119 | bdev->reg = ioremap(res->start, res->end - res->start + 1); | 119 | bdev->reg = ioremap(res->start, resource_size(res)); |
120 | dev_set_drvdata(&pdev->dev, bdev); | 120 | dev_set_drvdata(&pdev->dev, bdev); |
121 | 121 | ||
122 | error = input_register_polled_device(poll_dev); | 122 | error = input_register_polled_device(poll_dev); |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a63315ce4a6c..0918acae584a 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -23,30 +23,16 @@ | |||
23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver |
24 | * read those events from the small (32 event) queue and reports them. | 24 | * read those events from the small (32 event) queue and reports them. |
25 | * | 25 | * |
26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
28 | * using a work_struct. The IRQ is active low, but we use it through | ||
29 | * the GPIO controller so we can trigger on falling edges. | ||
30 | * | ||
31 | * Note that physically there can only be one of these devices. | 26 | * Note that physically there can only be one of these devices. |
32 | * | 27 | * |
33 | * This driver was tested with firmware revision A4. | 28 | * This driver was tested with firmware revision A4. |
34 | */ | 29 | */ |
35 | struct dm355evm_keys { | 30 | struct dm355evm_keys { |
36 | struct work_struct work; | ||
37 | struct input_dev *input; | 31 | struct input_dev *input; |
38 | struct device *dev; | 32 | struct device *dev; |
39 | int irq; | 33 | int irq; |
40 | }; | 34 | }; |
41 | 35 | ||
42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
43 | { | ||
44 | struct dm355evm_keys *keys = _keys; | ||
45 | |||
46 | schedule_work(&keys->work); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ |
51 | static struct { | 37 | static struct { |
52 | u16 event; | 38 | u16 event; |
@@ -110,13 +96,12 @@ static struct { | |||
110 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
111 | }; | 97 | }; |
112 | 98 | ||
113 | static void dm355evm_keys_work(struct work_struct *work) | 99 | /* runs in an IRQ thread -- can (and will!) sleep */ |
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
114 | { | 101 | { |
115 | struct dm355evm_keys *keys; | 102 | struct dm355evm_keys *keys = _keys; |
116 | int status; | 103 | int status; |
117 | 104 | ||
118 | keys = container_of(work, struct dm355evm_keys, work); | ||
119 | |||
120 | /* For simplicity we ignore INPUT_COUNT and just read | 105 | /* For simplicity we ignore INPUT_COUNT and just read |
121 | * events until we get the "queue empty" indicator. | 106 | * events until we get the "queue empty" indicator. |
122 | * Reading INPUT_LOW decrements the count. | 107 | * Reading INPUT_LOW decrements the count. |
@@ -183,6 +168,19 @@ static void dm355evm_keys_work(struct work_struct *work) | |||
183 | input_report_key(keys->input, keycode, 0); | 168 | input_report_key(keys->input, keycode, 0); |
184 | input_sync(keys->input); | 169 | input_sync(keys->input); |
185 | } | 170 | } |
171 | return IRQ_HANDLED; | ||
172 | } | ||
173 | |||
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; | ||
186 | } | 184 | } |
187 | 185 | ||
188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
@@ -233,7 +231,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
233 | 231 | ||
234 | keys->dev = &pdev->dev; | 232 | keys->dev = &pdev->dev; |
235 | keys->input = input; | 233 | keys->input = input; |
236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
237 | 234 | ||
238 | /* set up "threaded IRQ handler" */ | 235 | /* set up "threaded IRQ handler" */ |
239 | status = platform_get_irq(pdev, 0); | 236 | status = platform_get_irq(pdev, 0); |
@@ -260,9 +257,10 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
260 | 257 | ||
261 | /* REVISIT: flush the event queue? */ | 258 | /* REVISIT: flush the event queue? */ |
262 | 259 | ||
263 | status = request_irq(keys->irq, dm355evm_keys_irq, | 260 | status = request_threaded_irq(keys->irq, |
264 | IRQF_TRIGGER_FALLING, | 261 | dm355evm_keys_hardirq, dm355evm_keys_irq, |
265 | dev_name(&pdev->dev), keys); | 262 | IRQF_TRIGGER_FALLING, |
263 | dev_name(&pdev->dev), keys); | ||
266 | if (status < 0) | 264 | if (status < 0) |
267 | goto fail1; | 265 | goto fail1; |
268 | 266 | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 27ee976eb54c..11fd038a078f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -243,9 +243,9 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
243 | #define FE_UNTESTED 0x80 | 243 | #define FE_UNTESTED 0x80 |
244 | 244 | ||
245 | static struct key_entry *keymap; /* = NULL; Current key map */ | 245 | static struct key_entry *keymap; /* = NULL; Current key map */ |
246 | static int have_wifi; | 246 | static bool have_wifi; |
247 | static int have_bluetooth; | 247 | static bool have_bluetooth; |
248 | static int have_leds; | 248 | static int leds_present; /* bitmask of leds present */ |
249 | 249 | ||
250 | static int __init dmi_matched(const struct dmi_system_id *dmi) | 250 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
251 | { | 251 | { |
@@ -254,11 +254,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) | |||
254 | keymap = dmi->driver_data; | 254 | keymap = dmi->driver_data; |
255 | for (key = keymap; key->type != KE_END; key++) { | 255 | for (key = keymap; key->type != KE_END; key++) { |
256 | if (key->type == KE_WIFI) | 256 | if (key->type == KE_WIFI) |
257 | have_wifi = 1; | 257 | have_wifi = true; |
258 | else if (key->type == KE_BLUETOOTH) | 258 | else if (key->type == KE_BLUETOOTH) |
259 | have_bluetooth = 1; | 259 | have_bluetooth = true; |
260 | } | 260 | } |
261 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | 261 | leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); |
262 | 262 | ||
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
@@ -611,10 +611,24 @@ static struct key_entry keymap_wistron_generic[] __initdata = { | |||
611 | { KE_END, 0 } | 611 | { KE_END, 0 } |
612 | }; | 612 | }; |
613 | 613 | ||
614 | static struct key_entry keymap_aopen_1557[] __initdata = { | ||
615 | { KE_KEY, 0x01, {KEY_HELP} }, | ||
616 | { KE_KEY, 0x11, {KEY_PROG1} }, | ||
617 | { KE_KEY, 0x12, {KEY_PROG2} }, | ||
618 | { KE_WIFI, 0x30 }, | ||
619 | { KE_KEY, 0x22, {KEY_REWIND} }, | ||
620 | { KE_KEY, 0x23, {KEY_FORWARD} }, | ||
621 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | ||
622 | { KE_KEY, 0x25, {KEY_STOPCD} }, | ||
623 | { KE_KEY, 0x31, {KEY_MAIL} }, | ||
624 | { KE_KEY, 0x36, {KEY_WWW} }, | ||
625 | { KE_END, 0 } | ||
626 | }; | ||
627 | |||
614 | static struct key_entry keymap_prestigio[] __initdata = { | 628 | static struct key_entry keymap_prestigio[] __initdata = { |
615 | { KE_KEY, 0x11, {KEY_PROG1} }, | 629 | { KE_KEY, 0x11, {KEY_PROG1} }, |
616 | { KE_KEY, 0x12, {KEY_PROG2} }, | 630 | { KE_KEY, 0x12, {KEY_PROG2} }, |
617 | { KE_WIFI, 0x30 }, | 631 | { KE_WIFI, 0x30 }, |
618 | { KE_KEY, 0x22, {KEY_REWIND} }, | 632 | { KE_KEY, 0x22, {KEY_REWIND} }, |
619 | { KE_KEY, 0x23, {KEY_FORWARD} }, | 633 | { KE_KEY, 0x23, {KEY_FORWARD} }, |
620 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | 634 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, |
@@ -985,6 +999,8 @@ static int __init select_keymap(void) | |||
985 | if (keymap_name != NULL) { | 999 | if (keymap_name != NULL) { |
986 | if (strcmp (keymap_name, "1557/MS2141") == 0) | 1000 | if (strcmp (keymap_name, "1557/MS2141") == 0) |
987 | keymap = keymap_wistron_ms2141; | 1001 | keymap = keymap_wistron_ms2141; |
1002 | else if (strcmp (keymap_name, "aopen1557") == 0) | ||
1003 | keymap = keymap_aopen_1557; | ||
988 | else if (strcmp (keymap_name, "prestigio") == 0) | 1004 | else if (strcmp (keymap_name, "prestigio") == 0) |
989 | keymap = keymap_prestigio; | 1005 | keymap = keymap_prestigio; |
990 | else if (strcmp (keymap_name, "generic") == 0) | 1006 | else if (strcmp (keymap_name, "generic") == 0) |
@@ -1009,8 +1025,8 @@ static int __init select_keymap(void) | |||
1009 | 1025 | ||
1010 | static struct input_polled_dev *wistron_idev; | 1026 | static struct input_polled_dev *wistron_idev; |
1011 | static unsigned long jiffies_last_press; | 1027 | static unsigned long jiffies_last_press; |
1012 | static int wifi_enabled; | 1028 | static bool wifi_enabled; |
1013 | static int bluetooth_enabled; | 1029 | static bool bluetooth_enabled; |
1014 | 1030 | ||
1015 | static void report_key(struct input_dev *dev, unsigned int keycode) | 1031 | static void report_key(struct input_dev *dev, unsigned int keycode) |
1016 | { | 1032 | { |
@@ -1053,24 +1069,24 @@ static struct led_classdev wistron_wifi_led = { | |||
1053 | 1069 | ||
1054 | static void __devinit wistron_led_init(struct device *parent) | 1070 | static void __devinit wistron_led_init(struct device *parent) |
1055 | { | 1071 | { |
1056 | if (have_leds & FE_WIFI_LED) { | 1072 | if (leds_present & FE_WIFI_LED) { |
1057 | u16 wifi = bios_get_default_setting(WIFI); | 1073 | u16 wifi = bios_get_default_setting(WIFI); |
1058 | if (wifi & 1) { | 1074 | if (wifi & 1) { |
1059 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | 1075 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; |
1060 | if (led_classdev_register(parent, &wistron_wifi_led)) | 1076 | if (led_classdev_register(parent, &wistron_wifi_led)) |
1061 | have_leds &= ~FE_WIFI_LED; | 1077 | leds_present &= ~FE_WIFI_LED; |
1062 | else | 1078 | else |
1063 | bios_set_state(WIFI, wistron_wifi_led.brightness); | 1079 | bios_set_state(WIFI, wistron_wifi_led.brightness); |
1064 | 1080 | ||
1065 | } else | 1081 | } else |
1066 | have_leds &= ~FE_WIFI_LED; | 1082 | leds_present &= ~FE_WIFI_LED; |
1067 | } | 1083 | } |
1068 | 1084 | ||
1069 | if (have_leds & FE_MAIL_LED) { | 1085 | if (leds_present & FE_MAIL_LED) { |
1070 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | 1086 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ |
1071 | wistron_mail_led.brightness = LED_OFF; | 1087 | wistron_mail_led.brightness = LED_OFF; |
1072 | if (led_classdev_register(parent, &wistron_mail_led)) | 1088 | if (led_classdev_register(parent, &wistron_mail_led)) |
1073 | have_leds &= ~FE_MAIL_LED; | 1089 | leds_present &= ~FE_MAIL_LED; |
1074 | else | 1090 | else |
1075 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | 1091 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); |
1076 | } | 1092 | } |
@@ -1078,28 +1094,28 @@ static void __devinit wistron_led_init(struct device *parent) | |||
1078 | 1094 | ||
1079 | static void __devexit wistron_led_remove(void) | 1095 | static void __devexit wistron_led_remove(void) |
1080 | { | 1096 | { |
1081 | if (have_leds & FE_MAIL_LED) | 1097 | if (leds_present & FE_MAIL_LED) |
1082 | led_classdev_unregister(&wistron_mail_led); | 1098 | led_classdev_unregister(&wistron_mail_led); |
1083 | 1099 | ||
1084 | if (have_leds & FE_WIFI_LED) | 1100 | if (leds_present & FE_WIFI_LED) |
1085 | led_classdev_unregister(&wistron_wifi_led); | 1101 | led_classdev_unregister(&wistron_wifi_led); |
1086 | } | 1102 | } |
1087 | 1103 | ||
1088 | static inline void wistron_led_suspend(void) | 1104 | static inline void wistron_led_suspend(void) |
1089 | { | 1105 | { |
1090 | if (have_leds & FE_MAIL_LED) | 1106 | if (leds_present & FE_MAIL_LED) |
1091 | led_classdev_suspend(&wistron_mail_led); | 1107 | led_classdev_suspend(&wistron_mail_led); |
1092 | 1108 | ||
1093 | if (have_leds & FE_WIFI_LED) | 1109 | if (leds_present & FE_WIFI_LED) |
1094 | led_classdev_suspend(&wistron_wifi_led); | 1110 | led_classdev_suspend(&wistron_wifi_led); |
1095 | } | 1111 | } |
1096 | 1112 | ||
1097 | static inline void wistron_led_resume(void) | 1113 | static inline void wistron_led_resume(void) |
1098 | { | 1114 | { |
1099 | if (have_leds & FE_MAIL_LED) | 1115 | if (leds_present & FE_MAIL_LED) |
1100 | led_classdev_resume(&wistron_mail_led); | 1116 | led_classdev_resume(&wistron_mail_led); |
1101 | 1117 | ||
1102 | if (have_leds & FE_WIFI_LED) | 1118 | if (leds_present & FE_WIFI_LED) |
1103 | led_classdev_resume(&wistron_wifi_led); | 1119 | led_classdev_resume(&wistron_wifi_led); |
1104 | } | 1120 | } |
1105 | 1121 | ||
@@ -1312,7 +1328,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1312 | if (have_wifi) { | 1328 | if (have_wifi) { |
1313 | u16 wifi = bios_get_default_setting(WIFI); | 1329 | u16 wifi = bios_get_default_setting(WIFI); |
1314 | if (wifi & 1) | 1330 | if (wifi & 1) |
1315 | wifi_enabled = (wifi & 2) ? 1 : 0; | 1331 | wifi_enabled = wifi & 2; |
1316 | else | 1332 | else |
1317 | have_wifi = 0; | 1333 | have_wifi = 0; |
1318 | 1334 | ||
@@ -1323,15 +1339,16 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1323 | if (have_bluetooth) { | 1339 | if (have_bluetooth) { |
1324 | u16 bt = bios_get_default_setting(BLUETOOTH); | 1340 | u16 bt = bios_get_default_setting(BLUETOOTH); |
1325 | if (bt & 1) | 1341 | if (bt & 1) |
1326 | bluetooth_enabled = (bt & 2) ? 1 : 0; | 1342 | bluetooth_enabled = bt & 2; |
1327 | else | 1343 | else |
1328 | have_bluetooth = 0; | 1344 | have_bluetooth = false; |
1329 | 1345 | ||
1330 | if (have_bluetooth) | 1346 | if (have_bluetooth) |
1331 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1347 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1332 | } | 1348 | } |
1333 | 1349 | ||
1334 | wistron_led_init(&dev->dev); | 1350 | wistron_led_init(&dev->dev); |
1351 | |||
1335 | err = setup_input_dev(); | 1352 | err = setup_input_dev(); |
1336 | if (err) { | 1353 | if (err) { |
1337 | bios_detach(); | 1354 | bios_detach(); |
@@ -1352,7 +1369,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
1352 | } | 1369 | } |
1353 | 1370 | ||
1354 | #ifdef CONFIG_PM | 1371 | #ifdef CONFIG_PM |
1355 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1372 | static int wistron_suspend(struct device *dev) |
1356 | { | 1373 | { |
1357 | if (have_wifi) | 1374 | if (have_wifi) |
1358 | bios_set_state(WIFI, 0); | 1375 | bios_set_state(WIFI, 0); |
@@ -1361,10 +1378,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
1361 | bios_set_state(BLUETOOTH, 0); | 1378 | bios_set_state(BLUETOOTH, 0); |
1362 | 1379 | ||
1363 | wistron_led_suspend(); | 1380 | wistron_led_suspend(); |
1381 | |||
1364 | return 0; | 1382 | return 0; |
1365 | } | 1383 | } |
1366 | 1384 | ||
1367 | static int wistron_resume(struct platform_device *dev) | 1385 | static int wistron_resume(struct device *dev) |
1368 | { | 1386 | { |
1369 | if (have_wifi) | 1387 | if (have_wifi) |
1370 | bios_set_state(WIFI, wifi_enabled); | 1388 | bios_set_state(WIFI, wifi_enabled); |
@@ -1373,24 +1391,30 @@ static int wistron_resume(struct platform_device *dev) | |||
1373 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1391 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1374 | 1392 | ||
1375 | wistron_led_resume(); | 1393 | wistron_led_resume(); |
1394 | |||
1376 | poll_bios(true); | 1395 | poll_bios(true); |
1377 | 1396 | ||
1378 | return 0; | 1397 | return 0; |
1379 | } | 1398 | } |
1380 | #else | 1399 | |
1381 | #define wistron_suspend NULL | 1400 | static const struct dev_pm_ops wistron_pm_ops = { |
1382 | #define wistron_resume NULL | 1401 | .suspend = wistron_suspend, |
1402 | .resume = wistron_resume, | ||
1403 | .poweroff = wistron_suspend, | ||
1404 | .restore = wistron_resume, | ||
1405 | }; | ||
1383 | #endif | 1406 | #endif |
1384 | 1407 | ||
1385 | static struct platform_driver wistron_driver = { | 1408 | static struct platform_driver wistron_driver = { |
1386 | .driver = { | 1409 | .driver = { |
1387 | .name = "wistron-bios", | 1410 | .name = "wistron-bios", |
1388 | .owner = THIS_MODULE, | 1411 | .owner = THIS_MODULE, |
1412 | #if CONFIG_PM | ||
1413 | .pm = &wistron_pm_ops, | ||
1414 | #endif | ||
1389 | }, | 1415 | }, |
1390 | .probe = wistron_probe, | 1416 | .probe = wistron_probe, |
1391 | .remove = __devexit_p(wistron_remove), | 1417 | .remove = __devexit_p(wistron_remove), |
1392 | .suspend = wistron_suspend, | ||
1393 | .resume = wistron_resume, | ||
1394 | }; | 1418 | }; |
1395 | 1419 | ||
1396 | static int __init wb_module_init(void) | 1420 | static int __init wb_module_init(void) |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 8a2c5b14c8d8..3feeb3af8abd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -107,6 +107,14 @@ config MOUSE_PS2_ELANTECH | |||
107 | entries. For further information, | 107 | entries. For further information, |
108 | see <file:Documentation/input/elantech.txt>. | 108 | see <file:Documentation/input/elantech.txt>. |
109 | 109 | ||
110 | config MOUSE_PS2_SENTELIC | ||
111 | bool "Sentelic Finger Sensing Pad PS/2 protocol extension" | ||
112 | depends on MOUSE_PS2 | ||
113 | help | ||
114 | Say Y here if you have a laptop (such as MSI WIND Netbook) | ||
115 | with Sentelic Finger Sensing Pad touchpad. | ||
116 | |||
117 | If unsure, say N. | ||
110 | 118 | ||
111 | config MOUSE_PS2_TOUCHKIT | 119 | config MOUSE_PS2_TOUCHKIT |
112 | bool "eGalax TouchKit PS/2 protocol extension" | 120 | bool "eGalax TouchKit PS/2 protocol extension" |
@@ -262,14 +270,6 @@ config MOUSE_VSXXXAA | |||
262 | described in the source file). This driver also works with the | 270 | described in the source file). This driver also works with the |
263 | digitizer (VSXXX-AB) DEC produced. | 271 | digitizer (VSXXX-AB) DEC produced. |
264 | 272 | ||
265 | config MOUSE_HIL | ||
266 | tristate "HIL pointers (mice etc)." | ||
267 | depends on GSC || HP300 | ||
268 | select HP_SDC | ||
269 | select HIL_MLC | ||
270 | help | ||
271 | Say Y here to support HIL pointers. | ||
272 | |||
273 | config MOUSE_GPIO | 273 | config MOUSE_GPIO |
274 | tristate "GPIO mouse" | 274 | tristate "GPIO mouse" |
275 | depends on GENERIC_GPIO | 275 | depends on GENERIC_GPIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 010f265ec152..570c84a4a654 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -9,7 +9,6 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | |||
9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o |
11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | 11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o |
12 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
13 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
14 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
15 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o |
@@ -28,5 +27,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o | |||
28 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o |
29 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 28 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 29 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o | ||
31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o | 32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 5547e2429fbe..f36110689aae 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -279,7 +279,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int | |||
279 | * subsequent commands. It looks like glidepad is behind stickpointer, | 279 | * subsequent commands. It looks like glidepad is behind stickpointer, |
280 | * I'd thought it would be other way around... | 280 | * I'd thought it would be other way around... |
281 | */ | 281 | */ |
282 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 282 | static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) |
283 | { | 283 | { |
284 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 284 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
@@ -367,16 +367,16 @@ static int alps_poll(struct psmouse *psmouse) | |||
367 | { | 367 | { |
368 | struct alps_data *priv = psmouse->private; | 368 | struct alps_data *priv = psmouse->private; |
369 | unsigned char buf[6]; | 369 | unsigned char buf[6]; |
370 | int poll_failed; | 370 | bool poll_failed; |
371 | 371 | ||
372 | if (priv->i->flags & ALPS_PASS) | 372 | if (priv->i->flags & ALPS_PASS) |
373 | alps_passthrough_mode(psmouse, 1); | 373 | alps_passthrough_mode(psmouse, true); |
374 | 374 | ||
375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | 375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, |
376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | 376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; |
377 | 377 | ||
378 | if (priv->i->flags & ALPS_PASS) | 378 | if (priv->i->flags & ALPS_PASS) |
379 | alps_passthrough_mode(psmouse, 0); | 379 | alps_passthrough_mode(psmouse, false); |
380 | 380 | ||
381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | 381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) |
382 | return -1; | 382 | return -1; |
@@ -401,10 +401,12 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
401 | if (!priv->i) | 401 | if (!priv->i) |
402 | return -1; | 402 | return -1; |
403 | 403 | ||
404 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) | 404 | if ((priv->i->flags & ALPS_PASS) && |
405 | alps_passthrough_mode(psmouse, true)) { | ||
405 | return -1; | 406 | return -1; |
407 | } | ||
406 | 408 | ||
407 | if (alps_tap_mode(psmouse, 1)) { | 409 | if (alps_tap_mode(psmouse, true)) { |
408 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); | 410 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); |
409 | return -1; | 411 | return -1; |
410 | } | 412 | } |
@@ -414,8 +416,10 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
414 | return -1; | 416 | return -1; |
415 | } | 417 | } |
416 | 418 | ||
417 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) | 419 | if ((priv->i->flags & ALPS_PASS) && |
420 | alps_passthrough_mode(psmouse, false)) { | ||
418 | return -1; | 421 | return -1; |
422 | } | ||
419 | 423 | ||
420 | /* ALPS needs stream mode, otherwise it won't report any data */ | 424 | /* ALPS needs stream mode, otherwise it won't report any data */ |
421 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { | 425 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { |
@@ -519,7 +523,7 @@ init_fail: | |||
519 | return -1; | 523 | return -1; |
520 | } | 524 | } |
521 | 525 | ||
522 | int alps_detect(struct psmouse *psmouse, int set_properties) | 526 | int alps_detect(struct psmouse *psmouse, bool set_properties) |
523 | { | 527 | { |
524 | int version; | 528 | int version; |
525 | const struct alps_model_info *model; | 529 | const struct alps_model_info *model; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 4bbddc99962b..bc87936fee1a 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -26,10 +26,10 @@ struct alps_data { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | #ifdef CONFIG_MOUSE_PS2_ALPS | 28 | #ifdef CONFIG_MOUSE_PS2_ALPS |
29 | int alps_detect(struct psmouse *psmouse, int set_properties); | 29 | int alps_detect(struct psmouse *psmouse, bool set_properties); |
30 | int alps_init(struct psmouse *psmouse); | 30 | int alps_init(struct psmouse *psmouse); |
31 | #else | 31 | #else |
32 | inline int alps_detect(struct psmouse *psmouse, int set_properties) | 32 | inline int alps_detect(struct psmouse *psmouse, bool set_properties) |
33 | { | 33 | { |
34 | return -ENOSYS; | 34 | return -ENOSYS; |
35 | } | 35 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2d8fc0bf6923..0d1d33468b43 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -317,7 +317,7 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
317 | const struct tp_finger *f; | 317 | const struct tp_finger *f; |
318 | struct input_dev *input = dev->input; | 318 | struct input_dev *input = dev->input; |
319 | int raw_p, raw_w, raw_x, raw_y, raw_n; | 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; |
320 | int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; | 320 | int ptest, origin, ibt = 0, nmin = 0, nmax = 0; |
321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | 321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; |
322 | 322 | ||
323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) | 323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
@@ -345,21 +345,22 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
345 | /* set the integrated button if applicable */ | 345 | /* set the integrated button if applicable */ |
346 | if (c->tp_type == TYPE2) | 346 | if (c->tp_type == TYPE2) |
347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | 347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); |
348 | } | ||
349 | 348 | ||
350 | /* while tracking finger still valid, count all fingers */ | 349 | /* while tracking finger still valid, count all fingers */ |
351 | if (ptest > PRESSURE_LOW && origin) { | 350 | if (ptest > PRESSURE_LOW && origin) { |
352 | abs_p = ptest; | 351 | abs_p = ptest; |
353 | abs_w = int2bound(&c->w, raw_w); | 352 | abs_w = int2bound(&c->w, raw_w); |
354 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | 353 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); |
355 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | 354 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); |
356 | while (raw_n--) { | 355 | while (raw_n--) { |
357 | ptest = int2bound(&c->p, raw2int(f->force_major)); | 356 | ptest = int2bound(&c->p, |
358 | if (ptest > PRESSURE_LOW) | 357 | raw2int(f->force_major)); |
359 | nmax++; | 358 | if (ptest > PRESSURE_LOW) |
360 | if (ptest > PRESSURE_HIGH) | 359 | nmax++; |
361 | nmin++; | 360 | if (ptest > PRESSURE_HIGH) |
362 | f++; | 361 | nmin++; |
362 | f++; | ||
363 | } | ||
363 | } | 364 | } |
364 | } | 365 | } |
365 | 366 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 4bc78892ba91..fda35e615abf 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -553,7 +553,7 @@ static struct attribute_group elantech_attr_group = { | |||
553 | /* | 553 | /* |
554 | * Use magic knock to detect Elantech touchpad | 554 | * Use magic knock to detect Elantech touchpad |
555 | */ | 555 | */ |
556 | int elantech_detect(struct psmouse *psmouse, int set_properties) | 556 | int elantech_detect(struct psmouse *psmouse, bool set_properties) |
557 | { | 557 | { |
558 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 558 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
559 | unsigned char param[3]; | 559 | unsigned char param[3]; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ed848cc80814..feac5f7af966 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -109,10 +109,10 @@ struct elantech_data { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH | 111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH |
112 | int elantech_detect(struct psmouse *psmouse, int set_properties); | 112 | int elantech_detect(struct psmouse *psmouse, bool set_properties); |
113 | int elantech_init(struct psmouse *psmouse); | 113 | int elantech_init(struct psmouse *psmouse); |
114 | #else | 114 | #else |
115 | static inline int elantech_detect(struct psmouse *psmouse, int set_properties) | 115 | static inline int elantech_detect(struct psmouse *psmouse, bool set_properties) |
116 | { | 116 | { |
117 | return -ENOSYS; | 117 | return -ENOSYS; |
118 | } | 118 | } |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index a1ad2f1a7bb3..de1e553028b7 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -367,7 +367,36 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
367 | } | 367 | } |
368 | 368 | ||
369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
370 | hgpk_show_powered, hgpk_set_powered, 0); | 370 | hgpk_show_powered, hgpk_set_powered, false); |
371 | |||
372 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | ||
373 | void *data, char *buf) | ||
374 | { | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data, | ||
379 | const char *buf, size_t count) | ||
380 | { | ||
381 | struct hgpk_data *priv = psmouse->private; | ||
382 | unsigned long value; | ||
383 | int err; | ||
384 | |||
385 | err = strict_strtoul(buf, 10, &value); | ||
386 | if (err || value != 1) | ||
387 | return -EINVAL; | ||
388 | |||
389 | /* | ||
390 | * We queue work instead of doing recalibration right here | ||
391 | * to avoid adding locking to to hgpk_force_recalibrate() | ||
392 | * since workqueue provides serialization. | ||
393 | */ | ||
394 | psmouse_queue_work(psmouse, &priv->recalib_wq, 0); | ||
395 | return count; | ||
396 | } | ||
397 | |||
398 | __PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL, | ||
399 | hgpk_trigger_recal_show, hgpk_trigger_recal, false); | ||
371 | 400 | ||
372 | static void hgpk_disconnect(struct psmouse *psmouse) | 401 | static void hgpk_disconnect(struct psmouse *psmouse) |
373 | { | 402 | { |
@@ -375,6 +404,11 @@ static void hgpk_disconnect(struct psmouse *psmouse) | |||
375 | 404 | ||
376 | device_remove_file(&psmouse->ps2dev.serio->dev, | 405 | device_remove_file(&psmouse->ps2dev.serio->dev, |
377 | &psmouse_attr_powered.dattr); | 406 | &psmouse_attr_powered.dattr); |
407 | |||
408 | if (psmouse->model >= HGPK_MODEL_C) | ||
409 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
410 | &psmouse_attr_recalibrate.dattr); | ||
411 | |||
378 | psmouse_reset(psmouse); | 412 | psmouse_reset(psmouse); |
379 | kfree(priv); | 413 | kfree(priv); |
380 | } | 414 | } |
@@ -423,10 +457,25 @@ static int hgpk_register(struct psmouse *psmouse) | |||
423 | 457 | ||
424 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 458 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
425 | &psmouse_attr_powered.dattr); | 459 | &psmouse_attr_powered.dattr); |
426 | if (err) | 460 | if (err) { |
427 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | 461 | hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n"); |
462 | return err; | ||
463 | } | ||
428 | 464 | ||
429 | return err; | 465 | /* C-series touchpads added the recalibrate command */ |
466 | if (psmouse->model >= HGPK_MODEL_C) { | ||
467 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
468 | &psmouse_attr_recalibrate.dattr); | ||
469 | if (err) { | ||
470 | hgpk_err(psmouse, | ||
471 | "Failed creating 'recalibrate' sysfs node\n"); | ||
472 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
473 | &psmouse_attr_powered.dattr); | ||
474 | return err; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
430 | } | 479 | } |
431 | 480 | ||
432 | int hgpk_init(struct psmouse *psmouse) | 481 | int hgpk_init(struct psmouse *psmouse) |
@@ -440,7 +489,7 @@ int hgpk_init(struct psmouse *psmouse) | |||
440 | 489 | ||
441 | psmouse->private = priv; | 490 | psmouse->private = priv; |
442 | priv->psmouse = psmouse; | 491 | priv->psmouse = psmouse; |
443 | priv->powered = 1; | 492 | priv->powered = true; |
444 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | 493 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); |
445 | 494 | ||
446 | err = psmouse_reset(psmouse); | 495 | err = psmouse_reset(psmouse); |
@@ -483,7 +532,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | |||
483 | return param[2]; | 532 | return param[2]; |
484 | } | 533 | } |
485 | 534 | ||
486 | int hgpk_detect(struct psmouse *psmouse, int set_properties) | 535 | int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
487 | { | 536 | { |
488 | int version; | 537 | int version; |
489 | 538 | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index a4b2a96f5f54..d61cfd3ee9cb 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
@@ -15,7 +15,7 @@ enum hgpk_model_t { | |||
15 | 15 | ||
16 | struct hgpk_data { | 16 | struct hgpk_data { |
17 | struct psmouse *psmouse; | 17 | struct psmouse *psmouse; |
18 | int powered; | 18 | bool powered; |
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | 19 | int count, x_tally, y_tally; /* hardware workaround stuff */ |
20 | unsigned long recalib_window; | 20 | unsigned long recalib_window; |
21 | struct delayed_work recalib_wq; | 21 | struct delayed_work recalib_wq; |
@@ -33,10 +33,10 @@ struct hgpk_data { | |||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | 33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) |
34 | 34 | ||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | 35 | #ifdef CONFIG_MOUSE_PS2_OLPC |
36 | int hgpk_detect(struct psmouse *psmouse, int set_properties); | 36 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
37 | int hgpk_init(struct psmouse *psmouse); | 37 | int hgpk_init(struct psmouse *psmouse); |
38 | #else | 38 | #else |
39 | static inline int hgpk_detect(struct psmouse *psmouse, int set_properties) | 39 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
40 | { | 40 | { |
41 | return -ENODEV; | 41 | return -ENODEV; |
42 | } | 42 | } |
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c deleted file mode 100644 index 3263ce083bf0..000000000000 --- a/drivers/input/mouse/hil_ptr.c +++ /dev/null | |||
@@ -1,447 +0,0 @@ | |||
1 | /* | ||
2 | * Generic linux-input device driver for axis-bearing devices | ||
3 | * | ||
4 | * Copyright (c) 2001 Brian S. Julin | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions, and the following disclaimer, | ||
12 | * without modification. | ||
13 | * 2. The name of the author may not be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * Alternatively, this software may be distributed under the terms of the | ||
17 | * GNU General Public License ("GPL"). | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * | ||
29 | * References: | ||
30 | * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/hil.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/serio.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/pci_ids.h> | ||
42 | |||
43 | #define PREFIX "HIL PTR: " | ||
44 | #define HIL_GENERIC_NAME "HIL pointer device" | ||
45 | |||
46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | ||
47 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | ||
48 | MODULE_LICENSE("Dual BSD/GPL"); | ||
49 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); | ||
50 | |||
51 | #define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ | ||
52 | #undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ | ||
53 | |||
54 | |||
55 | #define HIL_PTR_MAX_LENGTH 16 | ||
56 | |||
57 | struct hil_ptr { | ||
58 | struct input_dev *dev; | ||
59 | struct serio *serio; | ||
60 | |||
61 | /* Input buffer and index for packets from HIL bus. */ | ||
62 | hil_packet data[HIL_PTR_MAX_LENGTH]; | ||
63 | int idx4; /* four counts per packet */ | ||
64 | |||
65 | /* Raw device info records from HIL bus, see hil.h for fields. */ | ||
66 | char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ | ||
67 | char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ | ||
68 | char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ | ||
69 | char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | ||
70 | |||
71 | /* Extra device details not contained in struct input_dev. */ | ||
72 | unsigned int nbtn, naxes; | ||
73 | unsigned int btnmap[7]; | ||
74 | |||
75 | /* Something to sleep around with. */ | ||
76 | struct semaphore sem; | ||
77 | }; | ||
78 | |||
79 | /* Process a complete packet after transfer from the HIL */ | ||
80 | static void hil_ptr_process_record(struct hil_ptr *ptr) | ||
81 | { | ||
82 | struct input_dev *dev = ptr->dev; | ||
83 | hil_packet *data = ptr->data; | ||
84 | hil_packet p; | ||
85 | int idx, i, cnt, laxis; | ||
86 | int ax16, absdev; | ||
87 | |||
88 | idx = ptr->idx4/4; | ||
89 | p = data[idx - 1]; | ||
90 | |||
91 | if ((p & ~HIL_CMDCT_POL) == | ||
92 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | ||
93 | goto report; | ||
94 | if ((p & ~HIL_CMDCT_RPL) == | ||
95 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | ||
96 | goto report; | ||
97 | |||
98 | /* Not a poll response. See if we are loading config records. */ | ||
99 | switch (p & HIL_PKT_DATA_MASK) { | ||
100 | case HIL_CMD_IDD: | ||
101 | for (i = 0; i < idx; i++) | ||
102 | ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
103 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
104 | ptr->idd[i] = 0; | ||
105 | break; | ||
106 | |||
107 | case HIL_CMD_RSC: | ||
108 | for (i = 0; i < idx; i++) | ||
109 | ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
110 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
111 | ptr->rsc[i] = 0; | ||
112 | break; | ||
113 | |||
114 | case HIL_CMD_EXD: | ||
115 | for (i = 0; i < idx; i++) | ||
116 | ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
117 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
118 | ptr->exd[i] = 0; | ||
119 | break; | ||
120 | |||
121 | case HIL_CMD_RNM: | ||
122 | for (i = 0; i < idx; i++) | ||
123 | ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
124 | for (; i < HIL_PTR_MAX_LENGTH + 1; i++) | ||
125 | ptr->rnm[i] = 0; | ||
126 | break; | ||
127 | |||
128 | default: | ||
129 | /* These occur when device isn't present */ | ||
130 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | ||
131 | break; | ||
132 | /* Anything else we'd like to know about. */ | ||
133 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | ||
134 | break; | ||
135 | } | ||
136 | goto out; | ||
137 | |||
138 | report: | ||
139 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
140 | printk(KERN_WARNING PREFIX | ||
141 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
142 | goto out; | ||
143 | } | ||
144 | |||
145 | i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
146 | laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; | ||
147 | laxis += i; | ||
148 | |||
149 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
150 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
151 | |||
152 | for (cnt = 1; i < laxis; i++) { | ||
153 | unsigned int lo,hi,val; | ||
154 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
155 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
156 | if (absdev) { | ||
157 | val = lo + (hi<<8); | ||
158 | #ifdef TABLET_AUTOADJUST | ||
159 | if (val < dev->absmin[ABS_X + i]) | ||
160 | dev->absmin[ABS_X + i] = val; | ||
161 | if (val > dev->absmax[ABS_X + i]) | ||
162 | dev->absmax[ABS_X + i] = val; | ||
163 | #endif | ||
164 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
165 | input_report_abs(dev, ABS_X + i, val); | ||
166 | } else { | ||
167 | val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); | ||
168 | if (i%3) | ||
169 | val *= -1; | ||
170 | input_report_rel(dev, REL_X + i, val); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | while (cnt < idx - 1) { | ||
175 | unsigned int btn; | ||
176 | int up; | ||
177 | btn = ptr->data[cnt++]; | ||
178 | up = btn & 1; | ||
179 | btn &= 0xfe; | ||
180 | if (btn == 0x8e) | ||
181 | continue; /* TODO: proximity == touch? */ | ||
182 | else | ||
183 | if ((btn > 0x8c) || (btn < 0x80)) | ||
184 | continue; | ||
185 | btn = (btn - 0x80) >> 1; | ||
186 | btn = ptr->btnmap[btn]; | ||
187 | input_report_key(dev, btn, !up); | ||
188 | } | ||
189 | input_sync(dev); | ||
190 | out: | ||
191 | ptr->idx4 = 0; | ||
192 | up(&ptr->sem); | ||
193 | } | ||
194 | |||
195 | static void hil_ptr_process_err(struct hil_ptr *ptr) | ||
196 | { | ||
197 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | ||
198 | ptr->idx4 = 0; | ||
199 | up(&ptr->sem); | ||
200 | } | ||
201 | |||
202 | static irqreturn_t hil_ptr_interrupt(struct serio *serio, | ||
203 | unsigned char data, unsigned int flags) | ||
204 | { | ||
205 | struct hil_ptr *ptr; | ||
206 | hil_packet packet; | ||
207 | int idx; | ||
208 | |||
209 | ptr = serio_get_drvdata(serio); | ||
210 | BUG_ON(ptr == NULL); | ||
211 | |||
212 | if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { | ||
213 | hil_ptr_process_err(ptr); | ||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | idx = ptr->idx4/4; | ||
217 | if (!(ptr->idx4 % 4)) | ||
218 | ptr->data[idx] = 0; | ||
219 | packet = ptr->data[idx]; | ||
220 | packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); | ||
221 | ptr->data[idx] = packet; | ||
222 | |||
223 | /* Records of N 4-byte hil_packets must terminate with a command. */ | ||
224 | if ((++(ptr->idx4)) % 4) | ||
225 | return IRQ_HANDLED; | ||
226 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | ||
227 | hil_ptr_process_err(ptr); | ||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | if (packet & HIL_PKT_CMD) | ||
231 | hil_ptr_process_record(ptr); | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static void hil_ptr_disconnect(struct serio *serio) | ||
237 | { | ||
238 | struct hil_ptr *ptr; | ||
239 | |||
240 | ptr = serio_get_drvdata(serio); | ||
241 | BUG_ON(ptr == NULL); | ||
242 | |||
243 | serio_close(serio); | ||
244 | input_unregister_device(ptr->dev); | ||
245 | kfree(ptr); | ||
246 | } | ||
247 | |||
248 | static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) | ||
249 | { | ||
250 | struct hil_ptr *ptr; | ||
251 | const char *txt; | ||
252 | unsigned int i, naxsets, btntype; | ||
253 | uint8_t did, *idd; | ||
254 | int error; | ||
255 | |||
256 | ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL); | ||
257 | if (!ptr) | ||
258 | return -ENOMEM; | ||
259 | |||
260 | ptr->dev = input_allocate_device(); | ||
261 | if (!ptr->dev) { | ||
262 | error = -ENOMEM; | ||
263 | goto bail0; | ||
264 | } | ||
265 | |||
266 | error = serio_open(serio, driver); | ||
267 | if (error) | ||
268 | goto bail1; | ||
269 | |||
270 | serio_set_drvdata(serio, ptr); | ||
271 | ptr->serio = serio; | ||
272 | |||
273 | init_MUTEX_LOCKED(&ptr->sem); | ||
274 | |||
275 | /* Get device info. MLC driver supplies devid/status/etc. */ | ||
276 | serio->write(serio, 0); | ||
277 | serio->write(serio, 0); | ||
278 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
279 | serio->write(serio, HIL_CMD_IDD); | ||
280 | down(&ptr->sem); | ||
281 | |||
282 | serio->write(serio, 0); | ||
283 | serio->write(serio, 0); | ||
284 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
285 | serio->write(serio, HIL_CMD_RSC); | ||
286 | down(&ptr->sem); | ||
287 | |||
288 | serio->write(serio, 0); | ||
289 | serio->write(serio, 0); | ||
290 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
291 | serio->write(serio, HIL_CMD_RNM); | ||
292 | down(&ptr->sem); | ||
293 | |||
294 | serio->write(serio, 0); | ||
295 | serio->write(serio, 0); | ||
296 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
297 | serio->write(serio, HIL_CMD_EXD); | ||
298 | down(&ptr->sem); | ||
299 | |||
300 | up(&ptr->sem); | ||
301 | |||
302 | did = ptr->idd[0]; | ||
303 | idd = ptr->idd + 1; | ||
304 | txt = "unknown"; | ||
305 | |||
306 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
307 | ptr->dev->evbit[0] = BIT_MASK(EV_REL); | ||
308 | txt = "relative"; | ||
309 | } | ||
310 | |||
311 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { | ||
312 | ptr->dev->evbit[0] = BIT_MASK(EV_ABS); | ||
313 | txt = "absolute"; | ||
314 | } | ||
315 | |||
316 | if (!ptr->dev->evbit[0]) { | ||
317 | error = -ENODEV; | ||
318 | goto bail2; | ||
319 | } | ||
320 | |||
321 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
322 | if (ptr->nbtn) | ||
323 | ptr->dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
324 | |||
325 | naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
326 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
327 | |||
328 | printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
329 | did, txt); | ||
330 | printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
331 | ptr->nbtn, naxsets, ptr->naxes); | ||
332 | |||
333 | btntype = BTN_MISC; | ||
334 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
335 | #ifdef TABLET_SIMULATES_MOUSE | ||
336 | btntype = BTN_TOUCH; | ||
337 | #else | ||
338 | btntype = BTN_DIGI; | ||
339 | #endif | ||
340 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
341 | btntype = BTN_TOUCH; | ||
342 | |||
343 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
344 | btntype = BTN_MOUSE; | ||
345 | |||
346 | for (i = 0; i < ptr->nbtn; i++) { | ||
347 | set_bit(btntype | i, ptr->dev->keybit); | ||
348 | ptr->btnmap[i] = btntype | i; | ||
349 | } | ||
350 | |||
351 | if (btntype == BTN_MOUSE) { | ||
352 | /* Swap buttons 2 and 3 */ | ||
353 | ptr->btnmap[1] = BTN_MIDDLE; | ||
354 | ptr->btnmap[2] = BTN_RIGHT; | ||
355 | } | ||
356 | |||
357 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
358 | for (i = 0; i < ptr->naxes; i++) | ||
359 | set_bit(REL_X + i, ptr->dev->relbit); | ||
360 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) | ||
361 | set_bit(REL_X + i, ptr->dev->relbit); | ||
362 | } else { | ||
363 | for (i = 0; i < ptr->naxes; i++) { | ||
364 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
365 | ptr->dev->absmin[ABS_X + i] = 0; | ||
366 | ptr->dev->absmax[ABS_X + i] = | ||
367 | HIL_IDD_AXIS_MAX((ptr->idd + 1), i); | ||
368 | } | ||
369 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { | ||
370 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
371 | ptr->dev->absmin[ABS_X + i] = 0; | ||
372 | ptr->dev->absmax[ABS_X + i] = | ||
373 | HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); | ||
374 | } | ||
375 | #ifdef TABLET_AUTOADJUST | ||
376 | for (i = 0; i < ABS_MAX; i++) { | ||
377 | int diff = ptr->dev->absmax[ABS_X + i] / 10; | ||
378 | ptr->dev->absmin[ABS_X + i] += diff; | ||
379 | ptr->dev->absmax[ABS_X + i] -= diff; | ||
380 | } | ||
381 | #endif | ||
382 | } | ||
383 | |||
384 | ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; | ||
385 | |||
386 | ptr->dev->id.bustype = BUS_HIL; | ||
387 | ptr->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
388 | ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ | ||
389 | ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ | ||
390 | ptr->dev->dev.parent = &serio->dev; | ||
391 | |||
392 | error = input_register_device(ptr->dev); | ||
393 | if (error) { | ||
394 | printk(KERN_INFO PREFIX "Unable to register input device\n"); | ||
395 | goto bail2; | ||
396 | } | ||
397 | |||
398 | printk(KERN_INFO "input: %s (%s), ID: %d\n", | ||
399 | ptr->dev->name, | ||
400 | (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", | ||
401 | did); | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | bail2: | ||
406 | serio_close(serio); | ||
407 | bail1: | ||
408 | input_free_device(ptr->dev); | ||
409 | bail0: | ||
410 | kfree(ptr); | ||
411 | serio_set_drvdata(serio, NULL); | ||
412 | return error; | ||
413 | } | ||
414 | |||
415 | static struct serio_device_id hil_ptr_ids[] = { | ||
416 | { | ||
417 | .type = SERIO_HIL_MLC, | ||
418 | .proto = SERIO_HIL, | ||
419 | .id = SERIO_ANY, | ||
420 | .extra = SERIO_ANY, | ||
421 | }, | ||
422 | { 0 } | ||
423 | }; | ||
424 | |||
425 | static struct serio_driver hil_ptr_serio_driver = { | ||
426 | .driver = { | ||
427 | .name = "hil_ptr", | ||
428 | }, | ||
429 | .description = "HP HIL mouse/tablet driver", | ||
430 | .id_table = hil_ptr_ids, | ||
431 | .connect = hil_ptr_connect, | ||
432 | .disconnect = hil_ptr_disconnect, | ||
433 | .interrupt = hil_ptr_interrupt | ||
434 | }; | ||
435 | |||
436 | static int __init hil_ptr_init(void) | ||
437 | { | ||
438 | return serio_register_driver(&hil_ptr_serio_driver); | ||
439 | } | ||
440 | |||
441 | static void __exit hil_ptr_exit(void) | ||
442 | { | ||
443 | serio_unregister_driver(&hil_ptr_serio_driver); | ||
444 | } | ||
445 | |||
446 | module_init(hil_ptr_init); | ||
447 | module_exit(hil_ptr_exit); | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index dcd4236af1e3..5e6308694408 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -33,11 +33,11 @@ static int lifebook_set_serio_phys(const struct dmi_system_id *d) | |||
33 | return 0; | 33 | return 0; |
34 | } | 34 | } |
35 | 35 | ||
36 | static unsigned char lifebook_use_6byte_proto; | 36 | static bool lifebook_use_6byte_proto; |
37 | 37 | ||
38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) | 38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) |
39 | { | 39 | { |
40 | lifebook_use_6byte_proto = 1; | 40 | lifebook_use_6byte_proto = true; |
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
@@ -125,7 +125,7 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | |||
125 | struct input_dev *dev1 = psmouse->dev; | 125 | struct input_dev *dev1 = psmouse->dev; |
126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; | 126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; |
127 | unsigned char *packet = psmouse->packet; | 127 | unsigned char *packet = psmouse->packet; |
128 | int relative_packet = packet[0] & 0x08; | 128 | bool relative_packet = packet[0] & 0x08; |
129 | 129 | ||
130 | if (relative_packet || !lifebook_use_6byte_proto) { | 130 | if (relative_packet || !lifebook_use_6byte_proto) { |
131 | if (psmouse->pktcnt != 3) | 131 | if (psmouse->pktcnt != 3) |
@@ -242,7 +242,7 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
242 | psmouse->private = NULL; | 242 | psmouse->private = NULL; |
243 | } | 243 | } |
244 | 244 | ||
245 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | 245 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
246 | { | 246 | { |
247 | if (!dmi_check_system(lifebook_dmi_table)) | 247 | if (!dmi_check_system(lifebook_dmi_table)) |
248 | return -1; | 248 | return -1; |
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index c1647cf036c2..407cb226bc0a 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h | |||
@@ -12,10 +12,10 @@ | |||
12 | #define _LIFEBOOK_H | 12 | #define _LIFEBOOK_H |
13 | 13 | ||
14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK | 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK |
15 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | 15 | int lifebook_detect(struct psmouse *psmouse, bool set_properties); |
16 | int lifebook_init(struct psmouse *psmouse); | 16 | int lifebook_init(struct psmouse *psmouse); |
17 | #else | 17 | #else |
18 | inline int lifebook_detect(struct psmouse *psmouse, int set_properties) | 18 | inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
19 | { | 19 | { |
20 | return -ENOSYS; | 20 | return -ENOSYS; |
21 | } | 21 | } |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 390f1dbb98a4..de745d751162 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -130,14 +130,11 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
130 | * 0 - disabled | 130 | * 0 - disabled |
131 | */ | 131 | */ |
132 | 132 | ||
133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscroll) | 133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll) |
134 | { | 134 | { |
135 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 135 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
136 | unsigned char param[4]; | 136 | unsigned char param[4]; |
137 | 137 | ||
138 | if (smartscroll > 1) | ||
139 | smartscroll = 1; | ||
140 | |||
141 | ps2pp_cmd(psmouse, param, 0x32); | 138 | ps2pp_cmd(psmouse, param, 0x32); |
142 | 139 | ||
143 | param[0] = 0; | 140 | param[0] = 0; |
@@ -149,12 +146,14 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr | |||
149 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 146 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
150 | } | 147 | } |
151 | 148 | ||
152 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf) | 149 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, |
150 | void *data, char *buf) | ||
153 | { | 151 | { |
154 | return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); | 152 | return sprintf(buf, "%d\n", psmouse->smartscroll); |
155 | } | 153 | } |
156 | 154 | ||
157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 155 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, |
156 | const char *buf, size_t count) | ||
158 | { | 157 | { |
159 | unsigned long value; | 158 | unsigned long value; |
160 | 159 | ||
@@ -261,29 +260,29 @@ static const struct ps2pp_info *get_model_info(unsigned char model) | |||
261 | 260 | ||
262 | static void ps2pp_set_model_properties(struct psmouse *psmouse, | 261 | static void ps2pp_set_model_properties(struct psmouse *psmouse, |
263 | const struct ps2pp_info *model_info, | 262 | const struct ps2pp_info *model_info, |
264 | int using_ps2pp) | 263 | bool using_ps2pp) |
265 | { | 264 | { |
266 | struct input_dev *input_dev = psmouse->dev; | 265 | struct input_dev *input_dev = psmouse->dev; |
267 | 266 | ||
268 | if (model_info->features & PS2PP_SIDE_BTN) | 267 | if (model_info->features & PS2PP_SIDE_BTN) |
269 | set_bit(BTN_SIDE, input_dev->keybit); | 268 | __set_bit(BTN_SIDE, input_dev->keybit); |
270 | 269 | ||
271 | if (model_info->features & PS2PP_EXTRA_BTN) | 270 | if (model_info->features & PS2PP_EXTRA_BTN) |
272 | set_bit(BTN_EXTRA, input_dev->keybit); | 271 | __set_bit(BTN_EXTRA, input_dev->keybit); |
273 | 272 | ||
274 | if (model_info->features & PS2PP_TASK_BTN) | 273 | if (model_info->features & PS2PP_TASK_BTN) |
275 | set_bit(BTN_TASK, input_dev->keybit); | 274 | __set_bit(BTN_TASK, input_dev->keybit); |
276 | 275 | ||
277 | if (model_info->features & PS2PP_NAV_BTN) { | 276 | if (model_info->features & PS2PP_NAV_BTN) { |
278 | set_bit(BTN_FORWARD, input_dev->keybit); | 277 | __set_bit(BTN_FORWARD, input_dev->keybit); |
279 | set_bit(BTN_BACK, input_dev->keybit); | 278 | __set_bit(BTN_BACK, input_dev->keybit); |
280 | } | 279 | } |
281 | 280 | ||
282 | if (model_info->features & PS2PP_WHEEL) | 281 | if (model_info->features & PS2PP_WHEEL) |
283 | set_bit(REL_WHEEL, input_dev->relbit); | 282 | __set_bit(REL_WHEEL, input_dev->relbit); |
284 | 283 | ||
285 | if (model_info->features & PS2PP_HWHEEL) | 284 | if (model_info->features & PS2PP_HWHEEL) |
286 | set_bit(REL_HWHEEL, input_dev->relbit); | 285 | __set_bit(REL_HWHEEL, input_dev->relbit); |
287 | 286 | ||
288 | switch (model_info->kind) { | 287 | switch (model_info->kind) { |
289 | case PS2PP_KIND_WHEEL: | 288 | case PS2PP_KIND_WHEEL: |
@@ -321,13 +320,13 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, | |||
321 | * that support it. | 320 | * that support it. |
322 | */ | 321 | */ |
323 | 322 | ||
324 | int ps2pp_init(struct psmouse *psmouse, int set_properties) | 323 | int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
325 | { | 324 | { |
326 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 325 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
327 | unsigned char param[4]; | 326 | unsigned char param[4]; |
328 | unsigned char model, buttons; | 327 | unsigned char model, buttons; |
329 | const struct ps2pp_info *model_info; | 328 | const struct ps2pp_info *model_info; |
330 | int use_ps2pp = 0; | 329 | bool use_ps2pp = false; |
331 | int error; | 330 | int error; |
332 | 331 | ||
333 | param[0] = 0; | 332 | param[0] = 0; |
@@ -364,7 +363,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
364 | param[0] = 0; | 363 | param[0] = 0; |
365 | if (!ps2_command(ps2dev, param, 0x13d1) && | 364 | if (!ps2_command(ps2dev, param, 0x13d1) && |
366 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { | 365 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { |
367 | use_ps2pp = 1; | 366 | use_ps2pp = true; |
368 | } | 367 | } |
369 | 368 | ||
370 | } else { | 369 | } else { |
@@ -376,8 +375,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
376 | if ((param[0] & 0x78) == 0x48 && | 375 | if ((param[0] & 0x78) == 0x48 && |
377 | (param[1] & 0xf3) == 0xc2 && | 376 | (param[1] & 0xf3) == 0xc2 && |
378 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { | 377 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { |
379 | ps2pp_set_smartscroll(psmouse, psmouse->smartscroll); | 378 | ps2pp_set_smartscroll(psmouse, false); |
380 | use_ps2pp = 1; | 379 | use_ps2pp = true; |
381 | } | 380 | } |
382 | } | 381 | } |
383 | } | 382 | } |
@@ -406,7 +405,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
406 | } | 405 | } |
407 | 406 | ||
408 | if (buttons < 3) | 407 | if (buttons < 3) |
409 | clear_bit(BTN_MIDDLE, psmouse->dev->keybit); | 408 | __clear_bit(BTN_MIDDLE, psmouse->dev->keybit); |
410 | 409 | ||
411 | if (model_info) | 410 | if (model_info) |
412 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); | 411 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); |
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h index 6e5712525fd6..0c186f0282d9 100644 --- a/drivers/input/mouse/logips2pp.h +++ b/drivers/input/mouse/logips2pp.h | |||
@@ -12,9 +12,9 @@ | |||
12 | #define _LOGIPS2PP_H | 12 | #define _LOGIPS2PP_H |
13 | 13 | ||
14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
15 | int ps2pp_init(struct psmouse *psmouse, int set_properties); | 15 | int ps2pp_init(struct psmouse *psmouse, bool set_properties); |
16 | #else | 16 | #else |
17 | inline int ps2pp_init(struct psmouse *psmouse, int set_properties) | 17 | inline int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
18 | { | 18 | { |
19 | return -ENOSYS; | 19 | return -ENOSYS; |
20 | } | 20 | } |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b407b355dceb..690aed905436 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
31 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
32 | #include "elantech.h" | 32 | #include "elantech.h" |
33 | #include "sentelic.h" | ||
33 | 34 | ||
34 | #define DRIVER_DESC "PS/2 mouse driver" | 35 | #define DRIVER_DESC "PS/2 mouse driver" |
35 | 36 | ||
@@ -108,10 +109,10 @@ static struct workqueue_struct *kpsmoused_wq; | |||
108 | 109 | ||
109 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
110 | enum psmouse_type type; | 111 | enum psmouse_type type; |
112 | bool maxproto; | ||
111 | const char *name; | 113 | const char *name; |
112 | const char *alias; | 114 | const char *alias; |
113 | int maxproto; | 115 | int (*detect)(struct psmouse *, bool); |
114 | int (*detect)(struct psmouse *, int); | ||
115 | int (*init)(struct psmouse *); | 116 | int (*init)(struct psmouse *); |
116 | }; | 117 | }; |
117 | 118 | ||
@@ -216,7 +217,7 @@ void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | |||
216 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 217 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
217 | { | 218 | { |
218 | psmouse->state = new_state; | 219 | psmouse->state = new_state; |
219 | psmouse->pktcnt = psmouse->out_of_sync = 0; | 220 | psmouse->pktcnt = psmouse->out_of_sync_cnt = 0; |
220 | psmouse->ps2dev.flags = 0; | 221 | psmouse->ps2dev.flags = 0; |
221 | psmouse->last = jiffies; | 222 | psmouse->last = jiffies; |
222 | } | 223 | } |
@@ -249,7 +250,7 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
249 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 250 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
250 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 251 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", |
251 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 252 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 253 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
253 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 254 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 255 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); |
255 | serio_reconnect(psmouse->ps2dev.serio); | 256 | serio_reconnect(psmouse->ps2dev.serio); |
@@ -261,8 +262,8 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
261 | 262 | ||
262 | case PSMOUSE_FULL_PACKET: | 263 | case PSMOUSE_FULL_PACKET: |
263 | psmouse->pktcnt = 0; | 264 | psmouse->pktcnt = 0; |
264 | if (psmouse->out_of_sync) { | 265 | if (psmouse->out_of_sync_cnt) { |
265 | psmouse->out_of_sync = 0; | 266 | psmouse->out_of_sync_cnt = 0; |
266 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | 267 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", |
267 | psmouse->name, psmouse->phys); | 268 | psmouse->name, psmouse->phys); |
268 | } | 269 | } |
@@ -408,7 +409,7 @@ int psmouse_reset(struct psmouse *psmouse) | |||
408 | /* | 409 | /* |
409 | * Genius NetMouse magic init. | 410 | * Genius NetMouse magic init. |
410 | */ | 411 | */ |
411 | static int genius_detect(struct psmouse *psmouse, int set_properties) | 412 | static int genius_detect(struct psmouse *psmouse, bool set_properties) |
412 | { | 413 | { |
413 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 414 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
414 | unsigned char param[4]; | 415 | unsigned char param[4]; |
@@ -424,9 +425,9 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
424 | return -1; | 425 | return -1; |
425 | 426 | ||
426 | if (set_properties) { | 427 | if (set_properties) { |
427 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 428 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
428 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 429 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
429 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 430 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
430 | 431 | ||
431 | psmouse->vendor = "Genius"; | 432 | psmouse->vendor = "Genius"; |
432 | psmouse->name = "Mouse"; | 433 | psmouse->name = "Mouse"; |
@@ -439,7 +440,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
439 | /* | 440 | /* |
440 | * IntelliMouse magic init. | 441 | * IntelliMouse magic init. |
441 | */ | 442 | */ |
442 | static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | 443 | static int intellimouse_detect(struct psmouse *psmouse, bool set_properties) |
443 | { | 444 | { |
444 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 445 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
445 | unsigned char param[2]; | 446 | unsigned char param[2]; |
@@ -456,8 +457,8 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
456 | return -1; | 457 | return -1; |
457 | 458 | ||
458 | if (set_properties) { | 459 | if (set_properties) { |
459 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 460 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
460 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 461 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
461 | 462 | ||
462 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 463 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
463 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; | 464 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; |
@@ -470,7 +471,7 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
470 | /* | 471 | /* |
471 | * Try IntelliMouse/Explorer magic init. | 472 | * Try IntelliMouse/Explorer magic init. |
472 | */ | 473 | */ |
473 | static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | 474 | static int im_explorer_detect(struct psmouse *psmouse, bool set_properties) |
474 | { | 475 | { |
475 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 476 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
476 | unsigned char param[2]; | 477 | unsigned char param[2]; |
@@ -497,11 +498,11 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
497 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | 498 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); |
498 | 499 | ||
499 | if (set_properties) { | 500 | if (set_properties) { |
500 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 501 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
501 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 502 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
502 | set_bit(REL_HWHEEL, psmouse->dev->relbit); | 503 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); |
503 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 504 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
504 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 505 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
505 | 506 | ||
506 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 507 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
507 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; | 508 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; |
@@ -514,7 +515,7 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
514 | /* | 515 | /* |
515 | * Kensington ThinkingMouse / ExpertMouse magic init. | 516 | * Kensington ThinkingMouse / ExpertMouse magic init. |
516 | */ | 517 | */ |
517 | static int thinking_detect(struct psmouse *psmouse, int set_properties) | 518 | static int thinking_detect(struct psmouse *psmouse, bool set_properties) |
518 | { | 519 | { |
519 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 520 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
520 | unsigned char param[2]; | 521 | unsigned char param[2]; |
@@ -535,7 +536,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
535 | return -1; | 536 | return -1; |
536 | 537 | ||
537 | if (set_properties) { | 538 | if (set_properties) { |
538 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 539 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
539 | 540 | ||
540 | psmouse->vendor = "Kensington"; | 541 | psmouse->vendor = "Kensington"; |
541 | psmouse->name = "ThinkingMouse"; | 542 | psmouse->name = "ThinkingMouse"; |
@@ -547,7 +548,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
547 | /* | 548 | /* |
548 | * Bare PS/2 protocol "detection". Always succeeds. | 549 | * Bare PS/2 protocol "detection". Always succeeds. |
549 | */ | 550 | */ |
550 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 551 | static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) |
551 | { | 552 | { |
552 | if (set_properties) { | 553 | if (set_properties) { |
553 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 554 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
@@ -561,12 +562,12 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | |||
561 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it | 562 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it |
562 | * must be forced by sysfs protocol writing. | 563 | * must be forced by sysfs protocol writing. |
563 | */ | 564 | */ |
564 | static int cortron_detect(struct psmouse *psmouse, int set_properties) | 565 | static int cortron_detect(struct psmouse *psmouse, bool set_properties) |
565 | { | 566 | { |
566 | if (set_properties) { | 567 | if (set_properties) { |
567 | psmouse->vendor = "Cortron"; | 568 | psmouse->vendor = "Cortron"; |
568 | psmouse->name = "PS/2 Trackball"; | 569 | psmouse->name = "PS/2 Trackball"; |
569 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 570 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
570 | } | 571 | } |
571 | 572 | ||
572 | return 0; | 573 | return 0; |
@@ -578,9 +579,9 @@ static int cortron_detect(struct psmouse *psmouse, int set_properties) | |||
578 | */ | 579 | */ |
579 | 580 | ||
580 | static int psmouse_extensions(struct psmouse *psmouse, | 581 | static int psmouse_extensions(struct psmouse *psmouse, |
581 | unsigned int max_proto, int set_properties) | 582 | unsigned int max_proto, bool set_properties) |
582 | { | 583 | { |
583 | int synaptics_hardware = 0; | 584 | bool synaptics_hardware = true; |
584 | 585 | ||
585 | /* | 586 | /* |
586 | * We always check for lifebook because it does not disturb mouse | 587 | * We always check for lifebook because it does not disturb mouse |
@@ -607,7 +608,7 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
607 | * can reset it properly after probing for intellimouse. | 608 | * can reset it properly after probing for intellimouse. |
608 | */ | 609 | */ |
609 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { | 610 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { |
610 | synaptics_hardware = 1; | 611 | synaptics_hardware = true; |
611 | 612 | ||
612 | if (max_proto > PSMOUSE_IMEX) { | 613 | if (max_proto > PSMOUSE_IMEX) { |
613 | if (!set_properties || synaptics_init(psmouse) == 0) | 614 | if (!set_properties || synaptics_init(psmouse) == 0) |
@@ -666,6 +667,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
666 | max_proto = PSMOUSE_IMEX; | 667 | max_proto = PSMOUSE_IMEX; |
667 | } | 668 | } |
668 | 669 | ||
670 | /* | ||
671 | * Try Finger Sensing Pad | ||
672 | */ | ||
673 | if (max_proto > PSMOUSE_IMEX) { | ||
674 | if (fsp_detect(psmouse, set_properties) == 0) { | ||
675 | if (!set_properties || fsp_init(psmouse) == 0) | ||
676 | return PSMOUSE_FSP; | ||
677 | /* | ||
678 | * Init failed, try basic relative protocols | ||
679 | */ | ||
680 | max_proto = PSMOUSE_IMEX; | ||
681 | } | ||
682 | } | ||
683 | |||
669 | if (max_proto > PSMOUSE_IMEX) { | 684 | if (max_proto > PSMOUSE_IMEX) { |
670 | if (genius_detect(psmouse, set_properties) == 0) | 685 | if (genius_detect(psmouse, set_properties) == 0) |
671 | return PSMOUSE_GENPS; | 686 | return PSMOUSE_GENPS; |
@@ -718,7 +733,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
718 | .type = PSMOUSE_PS2, | 733 | .type = PSMOUSE_PS2, |
719 | .name = "PS/2", | 734 | .name = "PS/2", |
720 | .alias = "bare", | 735 | .alias = "bare", |
721 | .maxproto = 1, | 736 | .maxproto = true, |
722 | .detect = ps2bare_detect, | 737 | .detect = ps2bare_detect, |
723 | }, | 738 | }, |
724 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 739 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
@@ -745,14 +760,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
745 | .type = PSMOUSE_IMPS, | 760 | .type = PSMOUSE_IMPS, |
746 | .name = "ImPS/2", | 761 | .name = "ImPS/2", |
747 | .alias = "imps", | 762 | .alias = "imps", |
748 | .maxproto = 1, | 763 | .maxproto = true, |
749 | .detect = intellimouse_detect, | 764 | .detect = intellimouse_detect, |
750 | }, | 765 | }, |
751 | { | 766 | { |
752 | .type = PSMOUSE_IMEX, | 767 | .type = PSMOUSE_IMEX, |
753 | .name = "ImExPS/2", | 768 | .name = "ImExPS/2", |
754 | .alias = "exps", | 769 | .alias = "exps", |
755 | .maxproto = 1, | 770 | .maxproto = true, |
756 | .detect = im_explorer_detect, | 771 | .detect = im_explorer_detect, |
757 | }, | 772 | }, |
758 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 773 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
@@ -813,7 +828,16 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
813 | .detect = elantech_detect, | 828 | .detect = elantech_detect, |
814 | .init = elantech_init, | 829 | .init = elantech_init, |
815 | }, | 830 | }, |
816 | #endif | 831 | #endif |
832 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
833 | { | ||
834 | .type = PSMOUSE_FSP, | ||
835 | .name = "FSPPS/2", | ||
836 | .alias = "fsp", | ||
837 | .detect = fsp_detect, | ||
838 | .init = fsp_init, | ||
839 | }, | ||
840 | #endif | ||
817 | { | 841 | { |
818 | .type = PSMOUSE_CORTRON, | 842 | .type = PSMOUSE_CORTRON, |
819 | .name = "CortronPS/2", | 843 | .name = "CortronPS/2", |
@@ -824,7 +848,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
824 | .type = PSMOUSE_AUTO, | 848 | .type = PSMOUSE_AUTO, |
825 | .name = "auto", | 849 | .name = "auto", |
826 | .alias = "any", | 850 | .alias = "any", |
827 | .maxproto = 1, | 851 | .maxproto = true, |
828 | }, | 852 | }, |
829 | }; | 853 | }; |
830 | 854 | ||
@@ -990,7 +1014,7 @@ static void psmouse_resync(struct work_struct *work) | |||
990 | container_of(work, struct psmouse, resync_work.work); | 1014 | container_of(work, struct psmouse, resync_work.work); |
991 | struct serio *serio = psmouse->ps2dev.serio; | 1015 | struct serio *serio = psmouse->ps2dev.serio; |
992 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 1016 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
993 | int failed = 0, enabled = 0; | 1017 | bool failed = false, enabled = false; |
994 | int i; | 1018 | int i; |
995 | 1019 | ||
996 | mutex_lock(&psmouse_mutex); | 1020 | mutex_lock(&psmouse_mutex); |
@@ -1017,9 +1041,9 @@ static void psmouse_resync(struct work_struct *work) | |||
1017 | 1041 | ||
1018 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | 1042 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { |
1019 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | 1043 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) |
1020 | failed = 1; | 1044 | failed = true; |
1021 | } else | 1045 | } else |
1022 | psmouse->acks_disable_command = 1; | 1046 | psmouse->acks_disable_command = true; |
1023 | 1047 | ||
1024 | /* | 1048 | /* |
1025 | * Poll the mouse. If it was reset the packet will be shorter than | 1049 | * Poll the mouse. If it was reset the packet will be shorter than |
@@ -1030,7 +1054,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1030 | */ | 1054 | */ |
1031 | if (!failed) { | 1055 | if (!failed) { |
1032 | if (psmouse->poll(psmouse)) | 1056 | if (psmouse->poll(psmouse)) |
1033 | failed = 1; | 1057 | failed = true; |
1034 | else { | 1058 | else { |
1035 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1059 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
1036 | for (i = 0; i < psmouse->pktsize; i++) { | 1060 | for (i = 0; i < psmouse->pktsize; i++) { |
@@ -1040,7 +1064,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1040 | break; | 1064 | break; |
1041 | } | 1065 | } |
1042 | if (rc != PSMOUSE_FULL_PACKET) | 1066 | if (rc != PSMOUSE_FULL_PACKET) |
1043 | failed = 1; | 1067 | failed = true; |
1044 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 1068 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
1045 | } | 1069 | } |
1046 | } | 1070 | } |
@@ -1051,7 +1075,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1051 | */ | 1075 | */ |
1052 | for (i = 0; i < 5; i++) { | 1076 | for (i = 0; i < 5; i++) { |
1053 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | 1077 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
1054 | enabled = 1; | 1078 | enabled = true; |
1055 | break; | 1079 | break; |
1056 | } | 1080 | } |
1057 | msleep(200); | 1081 | msleep(200); |
@@ -1060,7 +1084,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1060 | if (!enabled) { | 1084 | if (!enabled) { |
1061 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | 1085 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", |
1062 | psmouse->ps2dev.serio->phys); | 1086 | psmouse->ps2dev.serio->phys); |
1063 | failed = 1; | 1087 | failed = true; |
1064 | } | 1088 | } |
1065 | 1089 | ||
1066 | if (failed) { | 1090 | if (failed) { |
@@ -1187,7 +1211,8 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse | |||
1187 | psmouse->type = proto->type; | 1211 | psmouse->type = proto->type; |
1188 | } | 1212 | } |
1189 | else | 1213 | else |
1190 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1214 | psmouse->type = psmouse_extensions(psmouse, |
1215 | psmouse_max_proto, true); | ||
1191 | 1216 | ||
1192 | /* | 1217 | /* |
1193 | * If mouse's packet size is 3 there is no point in polling the | 1218 | * If mouse's packet size is 3 there is no point in polling the |
@@ -1342,8 +1367,10 @@ static int psmouse_reconnect(struct serio *serio) | |||
1342 | if (psmouse->reconnect(psmouse)) | 1367 | if (psmouse->reconnect(psmouse)) |
1343 | goto out; | 1368 | goto out; |
1344 | } else if (psmouse_probe(psmouse) < 0 || | 1369 | } else if (psmouse_probe(psmouse) < 0 || |
1345 | psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) | 1370 | psmouse->type != psmouse_extensions(psmouse, |
1371 | psmouse_max_proto, false)) { | ||
1346 | goto out; | 1372 | goto out; |
1373 | } | ||
1347 | 1374 | ||
1348 | /* ok, the device type (and capabilities) match the old one, | 1375 | /* ok, the device type (and capabilities) match the old one, |
1349 | * we can continue using it, complete intialization | 1376 | * we can continue using it, complete intialization |
@@ -1528,7 +1555,9 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1528 | 1555 | ||
1529 | while (serio->child) { | 1556 | while (serio->child) { |
1530 | if (++retry > 3) { | 1557 | if (++retry > 3) { |
1531 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | 1558 | printk(KERN_WARNING |
1559 | "psmouse: failed to destroy child port, " | ||
1560 | "protocol change aborted.\n"); | ||
1532 | input_free_device(new_dev); | 1561 | input_free_device(new_dev); |
1533 | return -EIO; | 1562 | return -EIO; |
1534 | } | 1563 | } |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 54ed267894bd..e053bdd137ff 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -47,10 +47,10 @@ struct psmouse { | |||
47 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
48 | unsigned char pktsize; | 48 | unsigned char pktsize; |
49 | unsigned char type; | 49 | unsigned char type; |
50 | unsigned char acks_disable_command; | 50 | bool acks_disable_command; |
51 | unsigned int model; | 51 | unsigned int model; |
52 | unsigned long last; | 52 | unsigned long last; |
53 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync_cnt; |
54 | unsigned long num_resyncs; | 54 | unsigned long num_resyncs; |
55 | enum psmouse_state state; | 55 | enum psmouse_state state; |
56 | char devname[64]; | 56 | char devname[64]; |
@@ -60,7 +60,7 @@ struct psmouse { | |||
60 | unsigned int resolution; | 60 | unsigned int resolution; |
61 | unsigned int resetafter; | 61 | unsigned int resetafter; |
62 | unsigned int resync_time; | 62 | unsigned int resync_time; |
63 | unsigned int smartscroll; /* Logitech only */ | 63 | bool smartscroll; /* Logitech only */ |
64 | 64 | ||
65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); |
66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); | 66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); |
@@ -91,6 +91,7 @@ enum psmouse_type { | |||
91 | PSMOUSE_CORTRON, | 91 | PSMOUSE_CORTRON, |
92 | PSMOUSE_HGPK, | 92 | PSMOUSE_HGPK, |
93 | PSMOUSE_ELANTECH, | 93 | PSMOUSE_ELANTECH, |
94 | PSMOUSE_FSP, | ||
94 | PSMOUSE_AUTO /* This one should always be last */ | 95 | PSMOUSE_AUTO /* This one should always be last */ |
95 | }; | 96 | }; |
96 | 97 | ||
@@ -107,7 +108,7 @@ struct psmouse_attribute { | |||
107 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); | 108 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); |
108 | ssize_t (*set)(struct psmouse *psmouse, void *data, | 109 | ssize_t (*set)(struct psmouse *psmouse, void *data, |
109 | const char *buf, size_t count); | 110 | const char *buf, size_t count); |
110 | int protect; | 111 | bool protect; |
111 | }; | 112 | }; |
112 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) | 113 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) |
113 | 114 | ||
@@ -116,9 +117,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
116 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 117 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
117 | const char *buf, size_t count); | 118 | const char *buf, size_t count); |
118 | 119 | ||
119 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ | 120 | #define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \ |
120 | static ssize_t _show(struct psmouse *, void *data, char *); \ | ||
121 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | ||
122 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
123 | .dattr = { \ | 122 | .dattr = { \ |
124 | .attr = { \ | 123 | .attr = { \ |
@@ -134,7 +133,20 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
134 | .protect = _protect, \ | 133 | .protect = _protect, \ |
135 | } | 134 | } |
136 | 135 | ||
137 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 136 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
138 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | 137 | static ssize_t _show(struct psmouse *, void *, char *); \ |
138 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
139 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) | ||
140 | |||
141 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
142 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, true) | ||
143 | |||
144 | #define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \ | ||
145 | static ssize_t _show(struct psmouse *, void *, char *); \ | ||
146 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, true) | ||
147 | |||
148 | #define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \ | ||
149 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
150 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) | ||
139 | 151 | ||
140 | #endif /* _PSMOUSE_H */ | 152 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c new file mode 100644 index 000000000000..84e2fc04d11b --- /dev/null +++ b/drivers/input/mouse/sentelic.c | |||
@@ -0,0 +1,867 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/libps2.h> | ||
27 | #include <linux/serio.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | |||
30 | #include "psmouse.h" | ||
31 | #include "sentelic.h" | ||
32 | |||
33 | /* | ||
34 | * Timeout for FSP PS/2 command only (in milliseconds). | ||
35 | */ | ||
36 | #define FSP_CMD_TIMEOUT 200 | ||
37 | #define FSP_CMD_TIMEOUT2 30 | ||
38 | |||
39 | /** Driver version. */ | ||
40 | static const char fsp_drv_ver[] = "1.0.0-K"; | ||
41 | |||
42 | /* | ||
43 | * Make sure that the value being sent to FSP will not conflict with | ||
44 | * possible sample rate values. | ||
45 | */ | ||
46 | static unsigned char fsp_test_swap_cmd(unsigned char reg_val) | ||
47 | { | ||
48 | switch (reg_val) { | ||
49 | case 10: case 20: case 40: case 60: case 80: case 100: case 200: | ||
50 | /* | ||
51 | * The requested value being sent to FSP matched to possible | ||
52 | * sample rates, swap the given value such that the hardware | ||
53 | * wouldn't get confused. | ||
54 | */ | ||
55 | return (reg_val >> 4) | (reg_val << 4); | ||
56 | default: | ||
57 | return reg_val; /* swap isn't necessary */ | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Make sure that the value being sent to FSP will not conflict with certain | ||
63 | * commands. | ||
64 | */ | ||
65 | static unsigned char fsp_test_invert_cmd(unsigned char reg_val) | ||
66 | { | ||
67 | switch (reg_val) { | ||
68 | case 0xe9: case 0xee: case 0xf2: case 0xff: | ||
69 | /* | ||
70 | * The requested value being sent to FSP matched to certain | ||
71 | * commands, inverse the given value such that the hardware | ||
72 | * wouldn't get confused. | ||
73 | */ | ||
74 | return ~reg_val; | ||
75 | default: | ||
76 | return reg_val; /* inversion isn't necessary */ | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | ||
81 | { | ||
82 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
83 | unsigned char param[3]; | ||
84 | unsigned char addr; | ||
85 | int rc = -1; | ||
86 | |||
87 | /* | ||
88 | * We need to shut off the device and switch it into command | ||
89 | * mode so we don't confuse our protocol handler. We don't need | ||
90 | * to do that for writes because sysfs set helper does this for | ||
91 | * us. | ||
92 | */ | ||
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
95 | mutex_lock(&ps2dev->cmd_mutex); | ||
96 | |||
97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
98 | goto out; | ||
99 | |||
100 | /* should return 0xfe(request for resending) */ | ||
101 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
102 | /* should return 0xfc(failed) */ | ||
103 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
104 | |||
105 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
106 | goto out; | ||
107 | |||
108 | if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
109 | ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2); | ||
110 | } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
111 | /* swapping is required */ | ||
112 | ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2); | ||
113 | /* expect 0xfe */ | ||
114 | } else { | ||
115 | /* swapping isn't necessary */ | ||
116 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
117 | /* expect 0xfe */ | ||
118 | } | ||
119 | /* should return 0xfc(failed) */ | ||
120 | ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT); | ||
121 | |||
122 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0) | ||
123 | goto out; | ||
124 | |||
125 | *reg_val = param[2]; | ||
126 | rc = 0; | ||
127 | |||
128 | out: | ||
129 | mutex_unlock(&ps2dev->cmd_mutex); | ||
130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | ||
133 | reg_addr, *reg_val, rc); | ||
134 | return rc; | ||
135 | } | ||
136 | |||
137 | static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | ||
138 | { | ||
139 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
140 | unsigned char v; | ||
141 | int rc = -1; | ||
142 | |||
143 | mutex_lock(&ps2dev->cmd_mutex); | ||
144 | |||
145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
146 | goto out; | ||
147 | |||
148 | if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
149 | /* inversion is required */ | ||
150 | ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2); | ||
151 | } else { | ||
152 | if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
153 | /* swapping is required */ | ||
154 | ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2); | ||
155 | } else { | ||
156 | /* swapping isn't necessary */ | ||
157 | ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2); | ||
158 | } | ||
159 | } | ||
160 | /* write the register address in correct order */ | ||
161 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
162 | |||
163 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
164 | return -1; | ||
165 | |||
166 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
167 | /* inversion is required */ | ||
168 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
169 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
170 | /* swapping is required */ | ||
171 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
172 | } else { | ||
173 | /* swapping isn't necessary */ | ||
174 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
175 | } | ||
176 | |||
177 | /* write the register value in correct order */ | ||
178 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
179 | rc = 0; | ||
180 | |||
181 | out: | ||
182 | mutex_unlock(&ps2dev->cmd_mutex); | ||
183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | ||
184 | reg_addr, reg_val, rc); | ||
185 | return rc; | ||
186 | } | ||
187 | |||
188 | /* Enable register clock gating for writing certain registers */ | ||
189 | static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable) | ||
190 | { | ||
191 | int v, nv; | ||
192 | |||
193 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1) | ||
194 | return -1; | ||
195 | |||
196 | if (enable) | ||
197 | nv = v | FSP_BIT_EN_REG_CLK; | ||
198 | else | ||
199 | nv = v & ~FSP_BIT_EN_REG_CLK; | ||
200 | |||
201 | /* only write if necessary */ | ||
202 | if (nv != v) | ||
203 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1) | ||
204 | return -1; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | ||
210 | { | ||
211 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
212 | unsigned char param[3]; | ||
213 | int rc = -1; | ||
214 | |||
215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
217 | mutex_lock(&ps2dev->cmd_mutex); | ||
218 | |||
219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
220 | goto out; | ||
221 | |||
222 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
223 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
224 | |||
225 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
226 | goto out; | ||
227 | |||
228 | ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2); | ||
229 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
230 | |||
231 | /* get the returned result */ | ||
232 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | ||
233 | goto out; | ||
234 | |||
235 | *reg_val = param[2]; | ||
236 | rc = 0; | ||
237 | |||
238 | out: | ||
239 | mutex_unlock(&ps2dev->cmd_mutex); | ||
240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | ||
243 | *reg_val, rc); | ||
244 | return rc; | ||
245 | } | ||
246 | |||
247 | static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | ||
248 | { | ||
249 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
250 | unsigned char v; | ||
251 | int rc = -1; | ||
252 | |||
253 | mutex_lock(&ps2dev->cmd_mutex); | ||
254 | |||
255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
256 | goto out; | ||
257 | |||
258 | ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2); | ||
259 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
260 | |||
261 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
262 | return -1; | ||
263 | |||
264 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
265 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
266 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
267 | /* swapping is required */ | ||
268 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
269 | } else { | ||
270 | /* swapping isn't necessary */ | ||
271 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
272 | } | ||
273 | |||
274 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
275 | rc = 0; | ||
276 | |||
277 | out: | ||
278 | mutex_unlock(&ps2dev->cmd_mutex); | ||
279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | ||
280 | reg_val, rc); | ||
281 | return rc; | ||
282 | } | ||
283 | |||
284 | static int fsp_get_version(struct psmouse *psmouse, int *version) | ||
285 | { | ||
286 | if (fsp_reg_read(psmouse, FSP_REG_VERSION, version)) | ||
287 | return -EIO; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int fsp_get_revision(struct psmouse *psmouse, int *rev) | ||
293 | { | ||
294 | if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev)) | ||
295 | return -EIO; | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int fsp_get_buttons(struct psmouse *psmouse, int *btn) | ||
301 | { | ||
302 | static const int buttons[] = { | ||
303 | 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */ | ||
304 | 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
305 | 0x04, /* Left/Middle/Right & Scroll Up/Down */ | ||
306 | 0x02, /* Left/Middle/Right */ | ||
307 | }; | ||
308 | int val; | ||
309 | |||
310 | if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1) | ||
311 | return -EIO; | ||
312 | |||
313 | *btn = buttons[(val & 0x30) >> 4]; | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | /* Enable on-pad command tag output */ | ||
318 | static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) | ||
319 | { | ||
320 | int v, nv; | ||
321 | int res = 0; | ||
322 | |||
323 | if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { | ||
324 | dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); | ||
325 | return -EIO; | ||
326 | } | ||
327 | |||
328 | if (enable) | ||
329 | nv = v | FSP_BIT_EN_OPC_TAG; | ||
330 | else | ||
331 | nv = v & ~FSP_BIT_EN_OPC_TAG; | ||
332 | |||
333 | /* only write if necessary */ | ||
334 | if (nv != v) { | ||
335 | fsp_reg_write_enable(psmouse, true); | ||
336 | res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv); | ||
337 | fsp_reg_write_enable(psmouse, false); | ||
338 | } | ||
339 | |||
340 | if (res != 0) { | ||
341 | dev_err(&psmouse->ps2dev.serio->dev, | ||
342 | "Unable to enable OPC tag.\n"); | ||
343 | res = -EIO; | ||
344 | } | ||
345 | |||
346 | return res; | ||
347 | } | ||
348 | |||
349 | static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable) | ||
350 | { | ||
351 | struct fsp_data *pad = psmouse->private; | ||
352 | int val; | ||
353 | |||
354 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
355 | return -EIO; | ||
356 | |||
357 | pad->vscroll = enable; | ||
358 | |||
359 | if (enable) | ||
360 | val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE); | ||
361 | else | ||
362 | val &= ~FSP_BIT_FIX_VSCR; | ||
363 | |||
364 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
365 | return -EIO; | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) | ||
371 | { | ||
372 | struct fsp_data *pad = psmouse->private; | ||
373 | int val, v2; | ||
374 | |||
375 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
376 | return -EIO; | ||
377 | |||
378 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2)) | ||
379 | return -EIO; | ||
380 | |||
381 | pad->hscroll = enable; | ||
382 | |||
383 | if (enable) { | ||
384 | val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE); | ||
385 | v2 |= FSP_BIT_EN_MSID6; | ||
386 | } else { | ||
387 | val &= ~FSP_BIT_FIX_HSCR; | ||
388 | v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8); | ||
389 | } | ||
390 | |||
391 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
392 | return -EIO; | ||
393 | |||
394 | /* reconfigure horizontal scrolling packet output */ | ||
395 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2)) | ||
396 | return -EIO; | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Write device specific initial parameters. | ||
403 | * | ||
404 | * ex: 0xab 0xcd - write oxcd into register 0xab | ||
405 | */ | ||
406 | static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, | ||
407 | const char *buf, size_t count) | ||
408 | { | ||
409 | unsigned long reg, val; | ||
410 | char *rest; | ||
411 | ssize_t retval; | ||
412 | |||
413 | reg = simple_strtoul(buf, &rest, 16); | ||
414 | if (rest == buf || *rest != ' ' || reg > 0xff) | ||
415 | return -EINVAL; | ||
416 | |||
417 | if (strict_strtoul(rest + 1, 16, &val) || val > 0xff) | ||
418 | return -EINVAL; | ||
419 | |||
420 | if (fsp_reg_write_enable(psmouse, true)) | ||
421 | return -EIO; | ||
422 | |||
423 | retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count; | ||
424 | |||
425 | fsp_reg_write_enable(psmouse, false); | ||
426 | |||
427 | return count; | ||
428 | } | ||
429 | |||
430 | PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); | ||
431 | |||
432 | static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse, | ||
433 | void *data, char *buf) | ||
434 | { | ||
435 | struct fsp_data *pad = psmouse->private; | ||
436 | |||
437 | return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val); | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Read a register from device. | ||
442 | * | ||
443 | * ex: 0xab -- read content from register 0xab | ||
444 | */ | ||
445 | static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, | ||
446 | const char *buf, size_t count) | ||
447 | { | ||
448 | struct fsp_data *pad = psmouse->private; | ||
449 | unsigned long reg; | ||
450 | int val; | ||
451 | |||
452 | if (strict_strtoul(buf, 16, ®) || reg > 0xff) | ||
453 | return -EINVAL; | ||
454 | |||
455 | if (fsp_reg_read(psmouse, reg, &val)) | ||
456 | return -EIO; | ||
457 | |||
458 | pad->last_reg = reg; | ||
459 | pad->last_val = val; | ||
460 | |||
461 | return count; | ||
462 | } | ||
463 | |||
464 | PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, | ||
465 | fsp_attr_show_getreg, fsp_attr_set_getreg); | ||
466 | |||
467 | static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, | ||
468 | void *data, char *buf) | ||
469 | { | ||
470 | int val = 0; | ||
471 | |||
472 | if (fsp_page_reg_read(psmouse, &val)) | ||
473 | return -EIO; | ||
474 | |||
475 | return sprintf(buf, "%02x\n", val); | ||
476 | } | ||
477 | |||
478 | static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, | ||
479 | const char *buf, size_t count) | ||
480 | { | ||
481 | unsigned long val; | ||
482 | |||
483 | if (strict_strtoul(buf, 16, &val) || val > 0xff) | ||
484 | return -EINVAL; | ||
485 | |||
486 | if (fsp_page_reg_write(psmouse, val)) | ||
487 | return -EIO; | ||
488 | |||
489 | return count; | ||
490 | } | ||
491 | |||
492 | PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, | ||
493 | fsp_attr_show_pagereg, fsp_attr_set_pagereg); | ||
494 | |||
495 | static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse, | ||
496 | void *data, char *buf) | ||
497 | { | ||
498 | struct fsp_data *pad = psmouse->private; | ||
499 | |||
500 | return sprintf(buf, "%d\n", pad->vscroll); | ||
501 | } | ||
502 | |||
503 | static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data, | ||
504 | const char *buf, size_t count) | ||
505 | { | ||
506 | unsigned long val; | ||
507 | |||
508 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
509 | return -EINVAL; | ||
510 | |||
511 | fsp_onpad_vscr(psmouse, val); | ||
512 | |||
513 | return count; | ||
514 | } | ||
515 | |||
516 | PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, | ||
517 | fsp_attr_show_vscroll, fsp_attr_set_vscroll); | ||
518 | |||
519 | static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse, | ||
520 | void *data, char *buf) | ||
521 | { | ||
522 | struct fsp_data *pad = psmouse->private; | ||
523 | |||
524 | return sprintf(buf, "%d\n", pad->hscroll); | ||
525 | } | ||
526 | |||
527 | static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | unsigned long val; | ||
531 | |||
532 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
533 | return -EINVAL; | ||
534 | |||
535 | fsp_onpad_hscr(psmouse, val); | ||
536 | |||
537 | return count; | ||
538 | } | ||
539 | |||
540 | PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, | ||
541 | fsp_attr_show_hscroll, fsp_attr_set_hscroll); | ||
542 | |||
543 | static ssize_t fsp_attr_show_flags(struct psmouse *psmouse, | ||
544 | void *data, char *buf) | ||
545 | { | ||
546 | struct fsp_data *pad = psmouse->private; | ||
547 | |||
548 | return sprintf(buf, "%c\n", | ||
549 | pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c'); | ||
550 | } | ||
551 | |||
552 | static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | struct fsp_data *pad = psmouse->private; | ||
556 | size_t i; | ||
557 | |||
558 | for (i = 0; i < count; i++) { | ||
559 | switch (buf[i]) { | ||
560 | case 'C': | ||
561 | pad->flags |= FSPDRV_FLAG_EN_OPC; | ||
562 | break; | ||
563 | case 'c': | ||
564 | pad->flags &= ~FSPDRV_FLAG_EN_OPC; | ||
565 | break; | ||
566 | default: | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | } | ||
570 | return count; | ||
571 | } | ||
572 | |||
573 | PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, | ||
574 | fsp_attr_show_flags, fsp_attr_set_flags); | ||
575 | |||
576 | static ssize_t fsp_attr_show_ver(struct psmouse *psmouse, | ||
577 | void *data, char *buf) | ||
578 | { | ||
579 | return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver); | ||
580 | } | ||
581 | |||
582 | PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); | ||
583 | |||
584 | static struct attribute *fsp_attributes[] = { | ||
585 | &psmouse_attr_setreg.dattr.attr, | ||
586 | &psmouse_attr_getreg.dattr.attr, | ||
587 | &psmouse_attr_page.dattr.attr, | ||
588 | &psmouse_attr_vscroll.dattr.attr, | ||
589 | &psmouse_attr_hscroll.dattr.attr, | ||
590 | &psmouse_attr_flags.dattr.attr, | ||
591 | &psmouse_attr_ver.dattr.attr, | ||
592 | NULL | ||
593 | }; | ||
594 | |||
595 | static struct attribute_group fsp_attribute_group = { | ||
596 | .attrs = fsp_attributes, | ||
597 | }; | ||
598 | |||
599 | #ifdef FSP_DEBUG | ||
600 | static void fsp_packet_debug(unsigned char packet[]) | ||
601 | { | ||
602 | static unsigned int ps2_packet_cnt; | ||
603 | static unsigned int ps2_last_second; | ||
604 | unsigned int jiffies_msec; | ||
605 | |||
606 | ps2_packet_cnt++; | ||
607 | jiffies_msec = jiffies_to_msecs(jiffies); | ||
608 | printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", | ||
609 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | ||
610 | |||
611 | if (jiffies_msec - ps2_last_second > 1000) { | ||
612 | printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt); | ||
613 | ps2_packet_cnt = 0; | ||
614 | ps2_last_second = jiffies_msec; | ||
615 | } | ||
616 | } | ||
617 | #else | ||
618 | static void fsp_packet_debug(unsigned char packet[]) | ||
619 | { | ||
620 | } | ||
621 | #endif | ||
622 | |||
623 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | ||
624 | { | ||
625 | struct input_dev *dev = psmouse->dev; | ||
626 | struct fsp_data *ad = psmouse->private; | ||
627 | unsigned char *packet = psmouse->packet; | ||
628 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; | ||
629 | int rel_x, rel_y; | ||
630 | |||
631 | if (psmouse->pktcnt < 4) | ||
632 | return PSMOUSE_GOOD_DATA; | ||
633 | |||
634 | /* | ||
635 | * Full packet accumulated, process it | ||
636 | */ | ||
637 | |||
638 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { | ||
639 | case FSP_PKT_TYPE_ABS: | ||
640 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
641 | "Unexpected absolute mode packet, ignored.\n"); | ||
642 | break; | ||
643 | |||
644 | case FSP_PKT_TYPE_NORMAL_OPC: | ||
645 | /* on-pad click, filter it if necessary */ | ||
646 | if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) | ||
647 | packet[0] &= ~BIT(0); | ||
648 | /* fall through */ | ||
649 | |||
650 | case FSP_PKT_TYPE_NORMAL: | ||
651 | /* normal packet */ | ||
652 | /* special packet data translation from on-pad packets */ | ||
653 | if (packet[3] != 0) { | ||
654 | if (packet[3] & BIT(0)) | ||
655 | button_status |= 0x01; /* wheel down */ | ||
656 | if (packet[3] & BIT(1)) | ||
657 | button_status |= 0x0f; /* wheel up */ | ||
658 | if (packet[3] & BIT(2)) | ||
659 | button_status |= BIT(5);/* horizontal left */ | ||
660 | if (packet[3] & BIT(3)) | ||
661 | button_status |= BIT(4);/* horizontal right */ | ||
662 | /* push back to packet queue */ | ||
663 | if (button_status != 0) | ||
664 | packet[3] = button_status; | ||
665 | rscroll = (packet[3] >> 4) & 1; | ||
666 | lscroll = (packet[3] >> 5) & 1; | ||
667 | } | ||
668 | /* | ||
669 | * Processing wheel up/down and extra button events | ||
670 | */ | ||
671 | input_report_rel(dev, REL_WHEEL, | ||
672 | (int)(packet[3] & 8) - (int)(packet[3] & 7)); | ||
673 | input_report_rel(dev, REL_HWHEEL, lscroll - rscroll); | ||
674 | input_report_key(dev, BTN_BACK, lscroll); | ||
675 | input_report_key(dev, BTN_FORWARD, rscroll); | ||
676 | |||
677 | /* | ||
678 | * Standard PS/2 Mouse | ||
679 | */ | ||
680 | input_report_key(dev, BTN_LEFT, packet[0] & 1); | ||
681 | input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); | ||
682 | input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); | ||
683 | |||
684 | rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0; | ||
685 | rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0; | ||
686 | |||
687 | input_report_rel(dev, REL_X, rel_x); | ||
688 | input_report_rel(dev, REL_Y, rel_y); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | input_sync(dev); | ||
693 | |||
694 | fsp_packet_debug(packet); | ||
695 | |||
696 | return PSMOUSE_FULL_PACKET; | ||
697 | } | ||
698 | |||
699 | static int fsp_activate_protocol(struct psmouse *psmouse) | ||
700 | { | ||
701 | struct fsp_data *pad = psmouse->private; | ||
702 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
703 | unsigned char param[2]; | ||
704 | int val; | ||
705 | |||
706 | /* | ||
707 | * Standard procedure to enter FSP Intellimouse mode | ||
708 | * (scrolling wheel, 4th and 5th buttons) | ||
709 | */ | ||
710 | param[0] = 200; | ||
711 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
712 | param[0] = 200; | ||
713 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
714 | param[0] = 80; | ||
715 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
716 | |||
717 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); | ||
718 | if (param[0] != 0x04) { | ||
719 | dev_err(&psmouse->ps2dev.serio->dev, | ||
720 | "Unable to enable 4 bytes packet format.\n"); | ||
721 | return -EIO; | ||
722 | } | ||
723 | |||
724 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { | ||
725 | dev_err(&psmouse->ps2dev.serio->dev, | ||
726 | "Unable to read SYSCTL5 register.\n"); | ||
727 | return -EIO; | ||
728 | } | ||
729 | |||
730 | val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); | ||
731 | /* Ensure we are not in absolute mode */ | ||
732 | val &= ~FSP_BIT_EN_PKT_G0; | ||
733 | if (pad->buttons == 0x06) { | ||
734 | /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
735 | val |= FSP_BIT_EN_MSID6; | ||
736 | } | ||
737 | |||
738 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { | ||
739 | dev_err(&psmouse->ps2dev.serio->dev, | ||
740 | "Unable to set up required mode bits.\n"); | ||
741 | return -EIO; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Enable OPC tags such that driver can tell the difference between | ||
746 | * on-pad and real button click | ||
747 | */ | ||
748 | if (fsp_opc_tag_enable(psmouse, true)) | ||
749 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
750 | "Failed to enable OPC tag mode.\n"); | ||
751 | |||
752 | /* Enable on-pad vertical and horizontal scrolling */ | ||
753 | fsp_onpad_vscr(psmouse, true); | ||
754 | fsp_onpad_hscr(psmouse, true); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | int fsp_detect(struct psmouse *psmouse, bool set_properties) | ||
760 | { | ||
761 | int id; | ||
762 | |||
763 | if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id)) | ||
764 | return -EIO; | ||
765 | |||
766 | if (id != 0x01) | ||
767 | return -ENODEV; | ||
768 | |||
769 | if (set_properties) { | ||
770 | psmouse->vendor = "Sentelic"; | ||
771 | psmouse->name = "FingerSensingPad"; | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static void fsp_reset(struct psmouse *psmouse) | ||
778 | { | ||
779 | fsp_opc_tag_enable(psmouse, false); | ||
780 | fsp_onpad_vscr(psmouse, false); | ||
781 | fsp_onpad_hscr(psmouse, false); | ||
782 | } | ||
783 | |||
784 | static void fsp_disconnect(struct psmouse *psmouse) | ||
785 | { | ||
786 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | ||
787 | &fsp_attribute_group); | ||
788 | |||
789 | fsp_reset(psmouse); | ||
790 | kfree(psmouse->private); | ||
791 | } | ||
792 | |||
793 | static int fsp_reconnect(struct psmouse *psmouse) | ||
794 | { | ||
795 | int version; | ||
796 | |||
797 | if (fsp_detect(psmouse, 0)) | ||
798 | return -ENODEV; | ||
799 | |||
800 | if (fsp_get_version(psmouse, &version)) | ||
801 | return -ENODEV; | ||
802 | |||
803 | if (fsp_activate_protocol(psmouse)) | ||
804 | return -EIO; | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | int fsp_init(struct psmouse *psmouse) | ||
810 | { | ||
811 | struct fsp_data *priv; | ||
812 | int ver, rev, buttons; | ||
813 | int error; | ||
814 | |||
815 | if (fsp_get_version(psmouse, &ver) || | ||
816 | fsp_get_revision(psmouse, &rev) || | ||
817 | fsp_get_buttons(psmouse, &buttons)) { | ||
818 | return -ENODEV; | ||
819 | } | ||
820 | |||
821 | printk(KERN_INFO | ||
822 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", | ||
823 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); | ||
824 | |||
825 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | ||
826 | if (!priv) | ||
827 | return -ENOMEM; | ||
828 | |||
829 | priv->ver = ver; | ||
830 | priv->rev = rev; | ||
831 | priv->buttons = buttons; | ||
832 | |||
833 | /* enable on-pad click by default */ | ||
834 | priv->flags |= FSPDRV_FLAG_EN_OPC; | ||
835 | |||
836 | /* Set up various supported input event bits */ | ||
837 | __set_bit(BTN_BACK, psmouse->dev->keybit); | ||
838 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); | ||
839 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | ||
840 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); | ||
841 | |||
842 | psmouse->protocol_handler = fsp_process_byte; | ||
843 | psmouse->disconnect = fsp_disconnect; | ||
844 | psmouse->reconnect = fsp_reconnect; | ||
845 | psmouse->cleanup = fsp_reset; | ||
846 | psmouse->pktsize = 4; | ||
847 | |||
848 | /* set default packet output based on number of buttons we found */ | ||
849 | error = fsp_activate_protocol(psmouse); | ||
850 | if (error) | ||
851 | goto err_out; | ||
852 | |||
853 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | ||
854 | &fsp_attribute_group); | ||
855 | if (error) { | ||
856 | dev_err(&psmouse->ps2dev.serio->dev, | ||
857 | "Failed to create sysfs attributes (%d)", error); | ||
858 | goto err_out; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | |||
863 | err_out: | ||
864 | kfree(psmouse->private); | ||
865 | psmouse->private = NULL; | ||
866 | return error; | ||
867 | } | ||
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h new file mode 100644 index 000000000000..ed1395ac7b8b --- /dev/null +++ b/drivers/input/mouse/sentelic.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __SENTELIC_H | ||
23 | #define __SENTELIC_H | ||
24 | |||
25 | /* Finger-sensing Pad information registers */ | ||
26 | #define FSP_REG_DEVICE_ID 0x00 | ||
27 | #define FSP_REG_VERSION 0x01 | ||
28 | #define FSP_REG_REVISION 0x04 | ||
29 | #define FSP_REG_TMOD_STATUS1 0x0B | ||
30 | #define FSP_BIT_NO_ROTATION BIT(3) | ||
31 | #define FSP_REG_PAGE_CTRL 0x0F | ||
32 | |||
33 | /* Finger-sensing Pad control registers */ | ||
34 | #define FSP_REG_SYSCTL1 0x10 | ||
35 | #define FSP_BIT_EN_REG_CLK BIT(5) | ||
36 | #define FSP_REG_OPC_QDOWN 0x31 | ||
37 | #define FSP_BIT_EN_OPC_TAG BIT(7) | ||
38 | #define FSP_REG_OPTZ_XLO 0x34 | ||
39 | #define FSP_REG_OPTZ_XHI 0x35 | ||
40 | #define FSP_REG_OPTZ_YLO 0x36 | ||
41 | #define FSP_REG_OPTZ_YHI 0x37 | ||
42 | #define FSP_REG_SYSCTL5 0x40 | ||
43 | #define FSP_BIT_90_DEGREE BIT(0) | ||
44 | #define FSP_BIT_EN_MSID6 BIT(1) | ||
45 | #define FSP_BIT_EN_MSID7 BIT(2) | ||
46 | #define FSP_BIT_EN_MSID8 BIT(3) | ||
47 | #define FSP_BIT_EN_AUTO_MSID8 BIT(5) | ||
48 | #define FSP_BIT_EN_PKT_G0 BIT(6) | ||
49 | |||
50 | #define FSP_REG_ONPAD_CTL 0x43 | ||
51 | #define FSP_BIT_ONPAD_ENABLE BIT(0) | ||
52 | #define FSP_BIT_ONPAD_FBBB BIT(1) | ||
53 | #define FSP_BIT_FIX_VSCR BIT(3) | ||
54 | #define FSP_BIT_FIX_HSCR BIT(5) | ||
55 | #define FSP_BIT_DRAG_LOCK BIT(6) | ||
56 | |||
57 | /* Finger-sensing Pad packet formating related definitions */ | ||
58 | |||
59 | /* absolute packet type */ | ||
60 | #define FSP_PKT_TYPE_NORMAL (0x00) | ||
61 | #define FSP_PKT_TYPE_ABS (0x01) | ||
62 | #define FSP_PKT_TYPE_NOTIFY (0x02) | ||
63 | #define FSP_PKT_TYPE_NORMAL_OPC (0x03) | ||
64 | #define FSP_PKT_TYPE_SHIFT (6) | ||
65 | |||
66 | #ifdef __KERNEL__ | ||
67 | |||
68 | struct fsp_data { | ||
69 | unsigned char ver; /* hardware version */ | ||
70 | unsigned char rev; /* hardware revison */ | ||
71 | unsigned char buttons; /* Number of buttons */ | ||
72 | unsigned int flags; | ||
73 | #define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ | ||
74 | |||
75 | bool vscroll; /* Vertical scroll zone enabled */ | ||
76 | bool hscroll; /* Horizontal scroll zone enabled */ | ||
77 | |||
78 | unsigned char last_reg; /* Last register we requested read from */ | ||
79 | unsigned char last_val; | ||
80 | }; | ||
81 | |||
82 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
83 | extern int fsp_detect(struct psmouse *psmouse, bool set_properties); | ||
84 | extern int fsp_init(struct psmouse *psmouse); | ||
85 | #else | ||
86 | inline int fsp_detect(struct psmouse *psmouse, bool set_properties) | ||
87 | { | ||
88 | return -ENOSYS; | ||
89 | } | ||
90 | inline int fsp_init(struct psmouse *psmouse) | ||
91 | { | ||
92 | return -ENOSYS; | ||
93 | } | ||
94 | #endif | ||
95 | |||
96 | #endif /* __KERNEL__ */ | ||
97 | |||
98 | #endif /* !__SENTELIC_H */ | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 19984bf06cad..b66ff1ac7dea 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -60,7 +60,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | int synaptics_detect(struct psmouse *psmouse, int set_properties) | 63 | int synaptics_detect(struct psmouse *psmouse, bool set_properties) |
64 | { | 64 | { |
65 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 65 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
66 | unsigned char param[4]; | 66 | unsigned char param[4]; |
@@ -556,38 +556,38 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
556 | { | 556 | { |
557 | int i; | 557 | int i; |
558 | 558 | ||
559 | set_bit(EV_ABS, dev->evbit); | 559 | __set_bit(EV_ABS, dev->evbit); |
560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); | 560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); |
561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); | 561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); |
562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
563 | set_bit(ABS_TOOL_WIDTH, dev->absbit); | 563 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); |
564 | 564 | ||
565 | set_bit(EV_KEY, dev->evbit); | 565 | __set_bit(EV_KEY, dev->evbit); |
566 | set_bit(BTN_TOUCH, dev->keybit); | 566 | __set_bit(BTN_TOUCH, dev->keybit); |
567 | set_bit(BTN_TOOL_FINGER, dev->keybit); | 567 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
568 | set_bit(BTN_LEFT, dev->keybit); | 568 | __set_bit(BTN_LEFT, dev->keybit); |
569 | set_bit(BTN_RIGHT, dev->keybit); | 569 | __set_bit(BTN_RIGHT, dev->keybit); |
570 | 570 | ||
571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
572 | set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 572 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
573 | set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 573 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
574 | } | 574 | } |
575 | 575 | ||
576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
577 | set_bit(BTN_MIDDLE, dev->keybit); | 577 | __set_bit(BTN_MIDDLE, dev->keybit); |
578 | 578 | ||
579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || | 579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || |
580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
581 | set_bit(BTN_FORWARD, dev->keybit); | 581 | __set_bit(BTN_FORWARD, dev->keybit); |
582 | set_bit(BTN_BACK, dev->keybit); | 582 | __set_bit(BTN_BACK, dev->keybit); |
583 | } | 583 | } |
584 | 584 | ||
585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
586 | set_bit(BTN_0 + i, dev->keybit); | 586 | __set_bit(BTN_0 + i, dev->keybit); |
587 | 587 | ||
588 | clear_bit(EV_REL, dev->evbit); | 588 | __clear_bit(EV_REL, dev->evbit); |
589 | clear_bit(REL_X, dev->relbit); | 589 | __clear_bit(REL_X, dev->relbit); |
590 | clear_bit(REL_Y, dev->relbit); | 590 | __clear_bit(REL_Y, dev->relbit); |
591 | 591 | ||
592 | dev->absres[ABS_X] = priv->x_res; | 592 | dev->absres[ABS_X] = priv->x_res; |
593 | dev->absres[ABS_Y] = priv->y_res; | 593 | dev->absres[ABS_Y] = priv->y_res; |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 302382151752..871f6fe377f9 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -105,7 +105,7 @@ struct synaptics_data { | |||
105 | int scroll; | 105 | int scroll; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | int synaptics_detect(struct psmouse *psmouse, int set_properties); | 108 | int synaptics_detect(struct psmouse *psmouse, bool set_properties); |
109 | int synaptics_init(struct psmouse *psmouse); | 109 | int synaptics_init(struct psmouse *psmouse); |
110 | void synaptics_reset(struct psmouse *psmouse); | 110 | void synaptics_reset(struct psmouse *psmouse); |
111 | 111 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 3fadb2accac0..0308a0faa94d 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c | |||
@@ -67,7 +67,7 @@ static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) | |||
67 | return PSMOUSE_FULL_PACKET; | 67 | return PSMOUSE_FULL_PACKET; |
68 | } | 68 | } |
69 | 69 | ||
70 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | 70 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties) |
71 | { | 71 | { |
72 | struct input_dev *dev = psmouse->dev; | 72 | struct input_dev *dev = psmouse->dev; |
73 | unsigned char param[3]; | 73 | unsigned char param[3]; |
@@ -86,7 +86,7 @@ int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | |||
86 | 86 | ||
87 | if (set_properties) { | 87 | if (set_properties) { |
88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
89 | set_bit(BTN_TOUCH, dev->keybit); | 89 | __set_bit(BTN_TOUCH, dev->keybit); |
90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); | 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); |
91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); | 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); |
92 | 92 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h index 8a0dd3574aef..2efe9ea29d0c 100644 --- a/drivers/input/mouse/touchkit_ps2.h +++ b/drivers/input/mouse/touchkit_ps2.h | |||
@@ -13,10 +13,10 @@ | |||
13 | #define _TOUCHKIT_PS2_H | 13 | #define _TOUCHKIT_PS2_H |
14 | 14 | ||
15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT | 15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT |
16 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties); | 16 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties); |
17 | #else | 17 | #else |
18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, | 18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, |
19 | int set_properties) | 19 | bool set_properties) |
20 | { | 20 | { |
21 | return -ENOSYS; | 21 | return -ENOSYS; |
22 | } | 22 | } |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index e68c814c4361..e354362f2971 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -282,7 +282,7 @@ static int trackpoint_reconnect(struct psmouse *psmouse) | |||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 285 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
286 | { | 286 | { |
287 | struct trackpoint_data *priv; | 287 | struct trackpoint_data *priv; |
288 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index c10a6e7d0101..e558a7096618 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h | |||
@@ -143,9 +143,9 @@ struct trackpoint_data | |||
143 | }; | 143 | }; |
144 | 144 | ||
145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT | 145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT |
146 | int trackpoint_detect(struct psmouse *psmouse, int set_properties); | 146 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties); |
147 | #else | 147 | #else |
148 | inline int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 148 | inline int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
149 | { | 149 | { |
150 | return -ENOSYS; | 150 | return -ENOSYS; |
151 | } | 151 | } |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 404eedd5ffa2..70111443678e 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -384,11 +384,11 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " |
385 | "incremental streaming mode and 72 samples/sec\n", | 385 | "incremental streaming mode and 72 samples/sec\n", |
386 | mouse->name, mouse->phys); | 386 | mouse->name, mouse->phys); |
387 | mouse->serio->write (mouse->serio, 'S'); /* Standard format */ | 387 | serio_write (mouse->serio, 'S'); /* Standard format */ |
388 | mdelay (50); | 388 | mdelay (50); |
389 | mouse->serio->write (mouse->serio, 'R'); /* Incremental */ | 389 | serio_write (mouse->serio, 'R'); /* Incremental */ |
390 | mdelay (50); | 390 | mdelay (50); |
391 | mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */ | 391 | serio_write (mouse->serio, 'L'); /* 72 samples/sec */ |
392 | } | 392 | } |
393 | 393 | ||
394 | static void | 394 | static void |
@@ -532,7 +532,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | |||
532 | * Request selftest. Standard packet format and differential | 532 | * Request selftest. Standard packet format and differential |
533 | * mode will be requested after the device ID'ed successfully. | 533 | * mode will be requested after the device ID'ed successfully. |
534 | */ | 534 | */ |
535 | serio->write (serio, 'T'); /* Test */ | 535 | serio_write (serio, 'T'); /* Test */ |
536 | 536 | ||
537 | err = input_register_device (input_dev); | 537 | err = input_register_device (input_dev); |
538 | if (err) | 538 | if (err) |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 41fda8c67b1e..a6fb7a3dcc46 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
@@ -231,7 +231,7 @@ static int __init psif_probe(struct platform_device *pdev) | |||
231 | goto out_free_io; | 231 | goto out_free_io; |
232 | } | 232 | } |
233 | 233 | ||
234 | psif->regs = ioremap(regs->start, regs->end - regs->start + 1); | 234 | psif->regs = ioremap(regs->start, resource_size(regs)); |
235 | if (!psif->regs) { | 235 | if (!psif->regs) { |
236 | ret = -ENOMEM; | 236 | ret = -ENOMEM; |
237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ccbf23ece8e3..a39bc4eb902b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -457,6 +457,34 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
457 | }, | 457 | }, |
458 | { } | 458 | { } |
459 | }; | 459 | }; |
460 | |||
461 | static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { | ||
462 | { | ||
463 | .ident = "Portable", | ||
464 | .matches = { | ||
465 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | ||
466 | }, | ||
467 | }, | ||
468 | { | ||
469 | .ident = "Laptop", | ||
470 | .matches = { | ||
471 | DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ | ||
472 | }, | ||
473 | }, | ||
474 | { | ||
475 | .ident = "Notebook", | ||
476 | .matches = { | ||
477 | DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ | ||
478 | }, | ||
479 | }, | ||
480 | { | ||
481 | .ident = "Sub-Notebook", | ||
482 | .matches = { | ||
483 | DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ | ||
484 | }, | ||
485 | }, | ||
486 | { } | ||
487 | }; | ||
460 | #endif | 488 | #endif |
461 | 489 | ||
462 | /* | 490 | /* |
@@ -530,9 +558,9 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
530 | #ifdef CONFIG_PNP | 558 | #ifdef CONFIG_PNP |
531 | #include <linux/pnp.h> | 559 | #include <linux/pnp.h> |
532 | 560 | ||
533 | static int i8042_pnp_kbd_registered; | 561 | static bool i8042_pnp_kbd_registered; |
534 | static unsigned int i8042_pnp_kbd_devices; | 562 | static unsigned int i8042_pnp_kbd_devices; |
535 | static int i8042_pnp_aux_registered; | 563 | static bool i8042_pnp_aux_registered; |
536 | static unsigned int i8042_pnp_aux_devices; | 564 | static unsigned int i8042_pnp_aux_devices; |
537 | 565 | ||
538 | static int i8042_pnp_command_reg; | 566 | static int i8042_pnp_command_reg; |
@@ -620,12 +648,12 @@ static struct pnp_driver i8042_pnp_aux_driver = { | |||
620 | static void i8042_pnp_exit(void) | 648 | static void i8042_pnp_exit(void) |
621 | { | 649 | { |
622 | if (i8042_pnp_kbd_registered) { | 650 | if (i8042_pnp_kbd_registered) { |
623 | i8042_pnp_kbd_registered = 0; | 651 | i8042_pnp_kbd_registered = false; |
624 | pnp_unregister_driver(&i8042_pnp_kbd_driver); | 652 | pnp_unregister_driver(&i8042_pnp_kbd_driver); |
625 | } | 653 | } |
626 | 654 | ||
627 | if (i8042_pnp_aux_registered) { | 655 | if (i8042_pnp_aux_registered) { |
628 | i8042_pnp_aux_registered = 0; | 656 | i8042_pnp_aux_registered = false; |
629 | pnp_unregister_driver(&i8042_pnp_aux_driver); | 657 | pnp_unregister_driver(&i8042_pnp_aux_driver); |
630 | } | 658 | } |
631 | } | 659 | } |
@@ -633,12 +661,12 @@ static void i8042_pnp_exit(void) | |||
633 | static int __init i8042_pnp_init(void) | 661 | static int __init i8042_pnp_init(void) |
634 | { | 662 | { |
635 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; | 663 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; |
636 | int pnp_data_busted = 0; | 664 | int pnp_data_busted = false; |
637 | int err; | 665 | int err; |
638 | 666 | ||
639 | #ifdef CONFIG_X86 | 667 | #ifdef CONFIG_X86 |
640 | if (dmi_check_system(i8042_dmi_nopnp_table)) | 668 | if (dmi_check_system(i8042_dmi_nopnp_table)) |
641 | i8042_nopnp = 1; | 669 | i8042_nopnp = true; |
642 | #endif | 670 | #endif |
643 | 671 | ||
644 | if (i8042_nopnp) { | 672 | if (i8042_nopnp) { |
@@ -648,11 +676,11 @@ static int __init i8042_pnp_init(void) | |||
648 | 676 | ||
649 | err = pnp_register_driver(&i8042_pnp_kbd_driver); | 677 | err = pnp_register_driver(&i8042_pnp_kbd_driver); |
650 | if (!err) | 678 | if (!err) |
651 | i8042_pnp_kbd_registered = 1; | 679 | i8042_pnp_kbd_registered = true; |
652 | 680 | ||
653 | err = pnp_register_driver(&i8042_pnp_aux_driver); | 681 | err = pnp_register_driver(&i8042_pnp_aux_driver); |
654 | if (!err) | 682 | if (!err) |
655 | i8042_pnp_aux_registered = 1; | 683 | i8042_pnp_aux_registered = true; |
656 | 684 | ||
657 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { | 685 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { |
658 | i8042_pnp_exit(); | 686 | i8042_pnp_exit(); |
@@ -680,9 +708,9 @@ static int __init i8042_pnp_init(void) | |||
680 | 708 | ||
681 | #if defined(__ia64__) | 709 | #if defined(__ia64__) |
682 | if (!i8042_pnp_kbd_devices) | 710 | if (!i8042_pnp_kbd_devices) |
683 | i8042_nokbd = 1; | 711 | i8042_nokbd = true; |
684 | if (!i8042_pnp_aux_devices) | 712 | if (!i8042_pnp_aux_devices) |
685 | i8042_noaux = 1; | 713 | i8042_noaux = true; |
686 | #endif | 714 | #endif |
687 | 715 | ||
688 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && | 716 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && |
@@ -693,7 +721,7 @@ static int __init i8042_pnp_init(void) | |||
693 | "using default %#x\n", | 721 | "using default %#x\n", |
694 | i8042_pnp_data_reg, i8042_data_reg); | 722 | i8042_pnp_data_reg, i8042_data_reg); |
695 | i8042_pnp_data_reg = i8042_data_reg; | 723 | i8042_pnp_data_reg = i8042_data_reg; |
696 | pnp_data_busted = 1; | 724 | pnp_data_busted = true; |
697 | } | 725 | } |
698 | 726 | ||
699 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && | 727 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && |
@@ -704,7 +732,7 @@ static int __init i8042_pnp_init(void) | |||
704 | "using default %#x\n", | 732 | "using default %#x\n", |
705 | i8042_pnp_command_reg, i8042_command_reg); | 733 | i8042_pnp_command_reg, i8042_command_reg); |
706 | i8042_pnp_command_reg = i8042_command_reg; | 734 | i8042_pnp_command_reg = i8042_command_reg; |
707 | pnp_data_busted = 1; | 735 | pnp_data_busted = true; |
708 | } | 736 | } |
709 | 737 | ||
710 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { | 738 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { |
@@ -712,7 +740,7 @@ static int __init i8042_pnp_init(void) | |||
712 | "PNP: PS/2 controller doesn't have KBD irq; " | 740 | "PNP: PS/2 controller doesn't have KBD irq; " |
713 | "using default %d\n", i8042_kbd_irq); | 741 | "using default %d\n", i8042_kbd_irq); |
714 | i8042_pnp_kbd_irq = i8042_kbd_irq; | 742 | i8042_pnp_kbd_irq = i8042_kbd_irq; |
715 | pnp_data_busted = 1; | 743 | pnp_data_busted = true; |
716 | } | 744 | } |
717 | 745 | ||
718 | if (!i8042_noaux && !i8042_pnp_aux_irq) { | 746 | if (!i8042_noaux && !i8042_pnp_aux_irq) { |
@@ -721,7 +749,7 @@ static int __init i8042_pnp_init(void) | |||
721 | "PNP: PS/2 appears to have AUX port disabled, " | 749 | "PNP: PS/2 appears to have AUX port disabled, " |
722 | "if this is incorrect please boot with " | 750 | "if this is incorrect please boot with " |
723 | "i8042.nopnp\n"); | 751 | "i8042.nopnp\n"); |
724 | i8042_noaux = 1; | 752 | i8042_noaux = true; |
725 | } else { | 753 | } else { |
726 | printk(KERN_WARNING | 754 | printk(KERN_WARNING |
727 | "PNP: PS/2 controller doesn't have AUX irq; " | 755 | "PNP: PS/2 controller doesn't have AUX irq; " |
@@ -735,6 +763,11 @@ static int __init i8042_pnp_init(void) | |||
735 | i8042_kbd_irq = i8042_pnp_kbd_irq; | 763 | i8042_kbd_irq = i8042_pnp_kbd_irq; |
736 | i8042_aux_irq = i8042_pnp_aux_irq; | 764 | i8042_aux_irq = i8042_pnp_aux_irq; |
737 | 765 | ||
766 | #ifdef CONFIG_X86 | ||
767 | i8042_bypass_aux_irq_test = !pnp_data_busted && | ||
768 | dmi_check_system(i8042_dmi_laptop_table); | ||
769 | #endif | ||
770 | |||
738 | return 0; | 771 | return 0; |
739 | } | 772 | } |
740 | 773 | ||
@@ -763,21 +796,21 @@ static int __init i8042_platform_init(void) | |||
763 | return retval; | 796 | return retval; |
764 | 797 | ||
765 | #if defined(__ia64__) | 798 | #if defined(__ia64__) |
766 | i8042_reset = 1; | 799 | i8042_reset = true; |
767 | #endif | 800 | #endif |
768 | 801 | ||
769 | #ifdef CONFIG_X86 | 802 | #ifdef CONFIG_X86 |
770 | if (dmi_check_system(i8042_dmi_reset_table)) | 803 | if (dmi_check_system(i8042_dmi_reset_table)) |
771 | i8042_reset = 1; | 804 | i8042_reset = true; |
772 | 805 | ||
773 | if (dmi_check_system(i8042_dmi_noloop_table)) | 806 | if (dmi_check_system(i8042_dmi_noloop_table)) |
774 | i8042_noloop = 1; | 807 | i8042_noloop = true; |
775 | 808 | ||
776 | if (dmi_check_system(i8042_dmi_nomux_table)) | 809 | if (dmi_check_system(i8042_dmi_nomux_table)) |
777 | i8042_nomux = 1; | 810 | i8042_nomux = true; |
778 | 811 | ||
779 | if (dmi_check_system(i8042_dmi_dritek_table)) | 812 | if (dmi_check_system(i8042_dmi_dritek_table)) |
780 | i8042_dritek = 1; | 813 | i8042_dritek = true; |
781 | #endif /* CONFIG_X86 */ | 814 | #endif /* CONFIG_X86 */ |
782 | 815 | ||
783 | return retval; | 816 | return retval; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 582245c497eb..eb3ff94af58c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -28,35 +28,35 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); | 28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); |
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | 30 | ||
31 | static unsigned int i8042_nokbd; | 31 | static bool i8042_nokbd; |
32 | module_param_named(nokbd, i8042_nokbd, bool, 0); | 32 | module_param_named(nokbd, i8042_nokbd, bool, 0); |
33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); | 33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); |
34 | 34 | ||
35 | static unsigned int i8042_noaux; | 35 | static bool i8042_noaux; |
36 | module_param_named(noaux, i8042_noaux, bool, 0); | 36 | module_param_named(noaux, i8042_noaux, bool, 0); |
37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); | 37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); |
38 | 38 | ||
39 | static unsigned int i8042_nomux; | 39 | static bool i8042_nomux; |
40 | module_param_named(nomux, i8042_nomux, bool, 0); | 40 | module_param_named(nomux, i8042_nomux, bool, 0); |
41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); | 41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); |
42 | 42 | ||
43 | static unsigned int i8042_unlock; | 43 | static bool i8042_unlock; |
44 | module_param_named(unlock, i8042_unlock, bool, 0); | 44 | module_param_named(unlock, i8042_unlock, bool, 0); |
45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); | 45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); |
46 | 46 | ||
47 | static unsigned int i8042_reset; | 47 | static bool i8042_reset; |
48 | module_param_named(reset, i8042_reset, bool, 0); | 48 | module_param_named(reset, i8042_reset, bool, 0); |
49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); | 49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); |
50 | 50 | ||
51 | static unsigned int i8042_direct; | 51 | static bool i8042_direct; |
52 | module_param_named(direct, i8042_direct, bool, 0); | 52 | module_param_named(direct, i8042_direct, bool, 0); |
53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); | 53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); |
54 | 54 | ||
55 | static unsigned int i8042_dumbkbd; | 55 | static bool i8042_dumbkbd; |
56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); | 56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); |
57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); | 57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); |
58 | 58 | ||
59 | static unsigned int i8042_noloop; | 59 | static bool i8042_noloop; |
60 | module_param_named(noloop, i8042_noloop, bool, 0); | 60 | module_param_named(noloop, i8042_noloop, bool, 0); |
61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
62 | 62 | ||
@@ -65,24 +65,26 @@ module_param_named(panicblink, i8042_blink_frequency, uint, 0600); | |||
65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); | 65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); |
66 | 66 | ||
67 | #ifdef CONFIG_X86 | 67 | #ifdef CONFIG_X86 |
68 | static unsigned int i8042_dritek; | 68 | static bool i8042_dritek; |
69 | module_param_named(dritek, i8042_dritek, bool, 0); | 69 | module_param_named(dritek, i8042_dritek, bool, 0); |
70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); | 70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #ifdef CONFIG_PNP | 73 | #ifdef CONFIG_PNP |
74 | static int i8042_nopnp; | 74 | static bool i8042_nopnp; |
75 | module_param_named(nopnp, i8042_nopnp, bool, 0); | 75 | module_param_named(nopnp, i8042_nopnp, bool, 0); |
76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); | 76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #define DEBUG | 79 | #define DEBUG |
80 | #ifdef DEBUG | 80 | #ifdef DEBUG |
81 | static int i8042_debug; | 81 | static bool i8042_debug; |
82 | module_param_named(debug, i8042_debug, bool, 0600); | 82 | module_param_named(debug, i8042_debug, bool, 0600); |
83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); | 83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | static bool i8042_bypass_aux_irq_test; | ||
87 | |||
86 | #include "i8042.h" | 88 | #include "i8042.h" |
87 | 89 | ||
88 | static DEFINE_SPINLOCK(i8042_lock); | 90 | static DEFINE_SPINLOCK(i8042_lock); |
@@ -90,7 +92,7 @@ static DEFINE_SPINLOCK(i8042_lock); | |||
90 | struct i8042_port { | 92 | struct i8042_port { |
91 | struct serio *serio; | 93 | struct serio *serio; |
92 | int irq; | 94 | int irq; |
93 | unsigned char exists; | 95 | bool exists; |
94 | signed char mux; | 96 | signed char mux; |
95 | }; | 97 | }; |
96 | 98 | ||
@@ -103,9 +105,9 @@ static struct i8042_port i8042_ports[I8042_NUM_PORTS]; | |||
103 | 105 | ||
104 | static unsigned char i8042_initial_ctr; | 106 | static unsigned char i8042_initial_ctr; |
105 | static unsigned char i8042_ctr; | 107 | static unsigned char i8042_ctr; |
106 | static unsigned char i8042_mux_present; | 108 | static bool i8042_mux_present; |
107 | static unsigned char i8042_kbd_irq_registered; | 109 | static bool i8042_kbd_irq_registered; |
108 | static unsigned char i8042_aux_irq_registered; | 110 | static bool i8042_aux_irq_registered; |
109 | static unsigned char i8042_suppress_kbd_ack; | 111 | static unsigned char i8042_suppress_kbd_ack; |
110 | static struct platform_device *i8042_platform_device; | 112 | static struct platform_device *i8042_platform_device; |
111 | 113 | ||
@@ -262,6 +264,49 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
262 | I8042_CMD_MUX_SEND + port->mux); | 264 | I8042_CMD_MUX_SEND + port->mux); |
263 | } | 265 | } |
264 | 266 | ||
267 | |||
268 | /* | ||
269 | * i8042_aux_close attempts to clear AUX or KBD port state by disabling | ||
270 | * and then re-enabling it. | ||
271 | */ | ||
272 | |||
273 | static void i8042_port_close(struct serio *serio) | ||
274 | { | ||
275 | int irq_bit; | ||
276 | int disable_bit; | ||
277 | const char *port_name; | ||
278 | |||
279 | if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { | ||
280 | irq_bit = I8042_CTR_AUXINT; | ||
281 | disable_bit = I8042_CTR_AUXDIS; | ||
282 | port_name = "AUX"; | ||
283 | } else { | ||
284 | irq_bit = I8042_CTR_KBDINT; | ||
285 | disable_bit = I8042_CTR_KBDDIS; | ||
286 | port_name = "KBD"; | ||
287 | } | ||
288 | |||
289 | i8042_ctr &= ~irq_bit; | ||
290 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
291 | printk(KERN_WARNING | ||
292 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
293 | port_name); | ||
294 | |||
295 | udelay(50); | ||
296 | |||
297 | i8042_ctr &= ~disable_bit; | ||
298 | i8042_ctr |= irq_bit; | ||
299 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
300 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | ||
301 | port_name); | ||
302 | |||
303 | /* | ||
304 | * See if there is any data appeared while we were messing with | ||
305 | * port state. | ||
306 | */ | ||
307 | i8042_interrupt(0, NULL); | ||
308 | } | ||
309 | |||
265 | /* | 310 | /* |
266 | * i8042_start() is called by serio core when port is about to finish | 311 | * i8042_start() is called by serio core when port is about to finish |
267 | * registering. It will mark port as existing so i8042_interrupt can | 312 | * registering. It will mark port as existing so i8042_interrupt can |
@@ -271,7 +316,7 @@ static int i8042_start(struct serio *serio) | |||
271 | { | 316 | { |
272 | struct i8042_port *port = serio->port_data; | 317 | struct i8042_port *port = serio->port_data; |
273 | 318 | ||
274 | port->exists = 1; | 319 | port->exists = true; |
275 | mb(); | 320 | mb(); |
276 | return 0; | 321 | return 0; |
277 | } | 322 | } |
@@ -285,7 +330,7 @@ static void i8042_stop(struct serio *serio) | |||
285 | { | 330 | { |
286 | struct i8042_port *port = serio->port_data; | 331 | struct i8042_port *port = serio->port_data; |
287 | 332 | ||
288 | port->exists = 0; | 333 | port->exists = false; |
289 | 334 | ||
290 | /* | 335 | /* |
291 | * We synchronize with both AUX and KBD IRQs because there is | 336 | * We synchronize with both AUX and KBD IRQs because there is |
@@ -391,7 +436,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
391 | } | 436 | } |
392 | 437 | ||
393 | /* | 438 | /* |
394 | * i8042_enable_kbd_port enables keybaord port on chip | 439 | * i8042_enable_kbd_port enables keyboard port on chip |
395 | */ | 440 | */ |
396 | 441 | ||
397 | static int i8042_enable_kbd_port(void) | 442 | static int i8042_enable_kbd_port(void) |
@@ -447,14 +492,15 @@ static int i8042_enable_mux_ports(void) | |||
447 | } | 492 | } |
448 | 493 | ||
449 | /* | 494 | /* |
450 | * i8042_set_mux_mode checks whether the controller has an active | 495 | * i8042_set_mux_mode checks whether the controller has an |
451 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. | 496 | * active multiplexor and puts the chip into Multiplexed (true) |
497 | * or Legacy (false) mode. | ||
452 | */ | 498 | */ |
453 | 499 | ||
454 | static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | 500 | static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) |
455 | { | 501 | { |
456 | 502 | ||
457 | unsigned char param; | 503 | unsigned char param, val; |
458 | /* | 504 | /* |
459 | * Get rid of bytes in the queue. | 505 | * Get rid of bytes in the queue. |
460 | */ | 506 | */ |
@@ -466,14 +512,21 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
466 | * mouse interface, the last should be version. | 512 | * mouse interface, the last should be version. |
467 | */ | 513 | */ |
468 | 514 | ||
469 | param = 0xf0; | 515 | param = val = 0xf0; |
470 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) | 516 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
471 | return -1; | 517 | return -1; |
472 | param = mode ? 0x56 : 0xf6; | 518 | param = val = multiplex ? 0x56 : 0xf6; |
473 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) | 519 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
474 | return -1; | 520 | return -1; |
475 | param = mode ? 0xa4 : 0xa5; | 521 | param = val = multiplex ? 0xa4 : 0xa5; |
476 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) | 522 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) |
523 | return -1; | ||
524 | |||
525 | /* | ||
526 | * Workaround for interference with USB Legacy emulation | ||
527 | * that causes a v10.12 MUX to be found. | ||
528 | */ | ||
529 | if (param == 0xac) | ||
477 | return -1; | 530 | return -1; |
478 | 531 | ||
479 | if (mux_version) | 532 | if (mux_version) |
@@ -488,18 +541,11 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
488 | * LCS/Telegraphics. | 541 | * LCS/Telegraphics. |
489 | */ | 542 | */ |
490 | 543 | ||
491 | static int __devinit i8042_check_mux(void) | 544 | static int __init i8042_check_mux(void) |
492 | { | 545 | { |
493 | unsigned char mux_version; | 546 | unsigned char mux_version; |
494 | 547 | ||
495 | if (i8042_set_mux_mode(1, &mux_version)) | 548 | if (i8042_set_mux_mode(true, &mux_version)) |
496 | return -1; | ||
497 | |||
498 | /* | ||
499 | * Workaround for interference with USB Legacy emulation | ||
500 | * that causes a v10.12 MUX to be found. | ||
501 | */ | ||
502 | if (mux_version == 0xAC) | ||
503 | return -1; | 549 | return -1; |
504 | 550 | ||
505 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | 551 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", |
@@ -516,7 +562,7 @@ static int __devinit i8042_check_mux(void) | |||
516 | return -EIO; | 562 | return -EIO; |
517 | } | 563 | } |
518 | 564 | ||
519 | i8042_mux_present = 1; | 565 | i8042_mux_present = true; |
520 | 566 | ||
521 | return 0; | 567 | return 0; |
522 | } | 568 | } |
@@ -524,10 +570,10 @@ static int __devinit i8042_check_mux(void) | |||
524 | /* | 570 | /* |
525 | * The following is used to test AUX IRQ delivery. | 571 | * The following is used to test AUX IRQ delivery. |
526 | */ | 572 | */ |
527 | static struct completion i8042_aux_irq_delivered __devinitdata; | 573 | static struct completion i8042_aux_irq_delivered __initdata; |
528 | static int i8042_irq_being_tested __devinitdata; | 574 | static bool i8042_irq_being_tested __initdata; |
529 | 575 | ||
530 | static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | 576 | static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) |
531 | { | 577 | { |
532 | unsigned long flags; | 578 | unsigned long flags; |
533 | unsigned char str, data; | 579 | unsigned char str, data; |
@@ -552,7 +598,7 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | |||
552 | * verifies success by readinng CTR. Used when testing for presence of AUX | 598 | * verifies success by readinng CTR. Used when testing for presence of AUX |
553 | * port. | 599 | * port. |
554 | */ | 600 | */ |
555 | static int __devinit i8042_toggle_aux(int on) | 601 | static int __init i8042_toggle_aux(bool on) |
556 | { | 602 | { |
557 | unsigned char param; | 603 | unsigned char param; |
558 | int i; | 604 | int i; |
@@ -580,11 +626,11 @@ static int __devinit i8042_toggle_aux(int on) | |||
580 | * the presence of an AUX interface. | 626 | * the presence of an AUX interface. |
581 | */ | 627 | */ |
582 | 628 | ||
583 | static int __devinit i8042_check_aux(void) | 629 | static int __init i8042_check_aux(void) |
584 | { | 630 | { |
585 | int retval = -1; | 631 | int retval = -1; |
586 | int irq_registered = 0; | 632 | bool irq_registered = false; |
587 | int aux_loop_broken = 0; | 633 | bool aux_loop_broken = false; |
588 | unsigned long flags; | 634 | unsigned long flags; |
589 | unsigned char param; | 635 | unsigned char param; |
590 | 636 | ||
@@ -621,19 +667,19 @@ static int __devinit i8042_check_aux(void) | |||
621 | * mark it as broken | 667 | * mark it as broken |
622 | */ | 668 | */ |
623 | if (!retval) | 669 | if (!retval) |
624 | aux_loop_broken = 1; | 670 | aux_loop_broken = true; |
625 | } | 671 | } |
626 | 672 | ||
627 | /* | 673 | /* |
628 | * Bit assignment test - filters out PS/2 i8042's in AT mode | 674 | * Bit assignment test - filters out PS/2 i8042's in AT mode |
629 | */ | 675 | */ |
630 | 676 | ||
631 | if (i8042_toggle_aux(0)) { | 677 | if (i8042_toggle_aux(false)) { |
632 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 678 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
633 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 679 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); |
634 | } | 680 | } |
635 | 681 | ||
636 | if (i8042_toggle_aux(1)) | 682 | if (i8042_toggle_aux(true)) |
637 | return -1; | 683 | return -1; |
638 | 684 | ||
639 | /* | 685 | /* |
@@ -641,7 +687,7 @@ static int __devinit i8042_check_aux(void) | |||
641 | * used it for a PCI card or somethig else. | 687 | * used it for a PCI card or somethig else. |
642 | */ | 688 | */ |
643 | 689 | ||
644 | if (i8042_noloop || aux_loop_broken) { | 690 | if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { |
645 | /* | 691 | /* |
646 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | 692 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port |
647 | * is working and hope we are right. | 693 | * is working and hope we are right. |
@@ -654,7 +700,7 @@ static int __devinit i8042_check_aux(void) | |||
654 | "i8042", i8042_platform_device)) | 700 | "i8042", i8042_platform_device)) |
655 | goto out; | 701 | goto out; |
656 | 702 | ||
657 | irq_registered = 1; | 703 | irq_registered = true; |
658 | 704 | ||
659 | if (i8042_enable_aux_port()) | 705 | if (i8042_enable_aux_port()) |
660 | goto out; | 706 | goto out; |
@@ -662,7 +708,7 @@ static int __devinit i8042_check_aux(void) | |||
662 | spin_lock_irqsave(&i8042_lock, flags); | 708 | spin_lock_irqsave(&i8042_lock, flags); |
663 | 709 | ||
664 | init_completion(&i8042_aux_irq_delivered); | 710 | init_completion(&i8042_aux_irq_delivered); |
665 | i8042_irq_being_tested = 1; | 711 | i8042_irq_being_tested = true; |
666 | 712 | ||
667 | param = 0xa5; | 713 | param = 0xa5; |
668 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); | 714 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); |
@@ -799,7 +845,7 @@ static int i8042_controller_init(void) | |||
799 | */ | 845 | */ |
800 | 846 | ||
801 | if (~i8042_ctr & I8042_CTR_XLATE) | 847 | if (~i8042_ctr & I8042_CTR_XLATE) |
802 | i8042_direct = 1; | 848 | i8042_direct = true; |
803 | 849 | ||
804 | /* | 850 | /* |
805 | * Set nontranslated mode for the kbd interface if requested by an option. | 851 | * Set nontranslated mode for the kbd interface if requested by an option. |
@@ -839,12 +885,15 @@ static void i8042_controller_reset(void) | |||
839 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; | 885 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; |
840 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 886 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
841 | 887 | ||
888 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
889 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | ||
890 | |||
842 | /* | 891 | /* |
843 | * Disable MUX mode if present. | 892 | * Disable MUX mode if present. |
844 | */ | 893 | */ |
845 | 894 | ||
846 | if (i8042_mux_present) | 895 | if (i8042_mux_present) |
847 | i8042_set_mux_mode(0, NULL); | 896 | i8042_set_mux_mode(false, NULL); |
848 | 897 | ||
849 | /* | 898 | /* |
850 | * Reset the controller if requested. | 899 | * Reset the controller if requested. |
@@ -923,41 +972,27 @@ static void i8042_dritek_enable(void) | |||
923 | 972 | ||
924 | #ifdef CONFIG_PM | 973 | #ifdef CONFIG_PM |
925 | 974 | ||
926 | static bool i8042_suspended; | ||
927 | |||
928 | /* | 975 | /* |
929 | * Here we try to restore the original BIOS settings. We only want to | 976 | * Here we try to restore the original BIOS settings to avoid |
930 | * do that once, when we really suspend, not when we taking memory | 977 | * upsetting it. |
931 | * snapshot for swsusp (in this case we'll perform required cleanup | ||
932 | * as part of shutdown process). | ||
933 | */ | 978 | */ |
934 | 979 | ||
935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 980 | static int i8042_pm_reset(struct device *dev) |
936 | { | 981 | { |
937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) | 982 | i8042_controller_reset(); |
938 | i8042_controller_reset(); | ||
939 | |||
940 | i8042_suspended = state.event == PM_EVENT_SUSPEND || | ||
941 | state.event == PM_EVENT_FREEZE; | ||
942 | 983 | ||
943 | return 0; | 984 | return 0; |
944 | } | 985 | } |
945 | 986 | ||
946 | |||
947 | /* | 987 | /* |
948 | * Here we try to reset everything back to a state in which suspended | 988 | * Here we try to reset everything back to a state we had |
989 | * before suspending. | ||
949 | */ | 990 | */ |
950 | 991 | ||
951 | static int i8042_resume(struct platform_device *dev) | 992 | static int i8042_pm_restore(struct device *dev) |
952 | { | 993 | { |
953 | int error; | 994 | int error; |
954 | 995 | ||
955 | /* | ||
956 | * Do not bother with restoring state if we haven't suspened yet | ||
957 | */ | ||
958 | if (!i8042_suspended) | ||
959 | return 0; | ||
960 | |||
961 | error = i8042_controller_check(); | 996 | error = i8042_controller_check(); |
962 | if (error) | 997 | if (error) |
963 | return error; | 998 | return error; |
@@ -991,7 +1026,7 @@ static int i8042_resume(struct platform_device *dev) | |||
991 | #endif | 1026 | #endif |
992 | 1027 | ||
993 | if (i8042_mux_present) { | 1028 | if (i8042_mux_present) { |
994 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) | 1029 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) |
995 | printk(KERN_WARNING | 1030 | printk(KERN_WARNING |
996 | "i8042: failed to resume active multiplexor, " | 1031 | "i8042: failed to resume active multiplexor, " |
997 | "mouse won't work.\n"); | 1032 | "mouse won't work.\n"); |
@@ -1001,11 +1036,18 @@ static int i8042_resume(struct platform_device *dev) | |||
1001 | if (i8042_ports[I8042_KBD_PORT_NO].serio) | 1036 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
1002 | i8042_enable_kbd_port(); | 1037 | i8042_enable_kbd_port(); |
1003 | 1038 | ||
1004 | i8042_suspended = false; | ||
1005 | i8042_interrupt(0, NULL); | 1039 | i8042_interrupt(0, NULL); |
1006 | 1040 | ||
1007 | return 0; | 1041 | return 0; |
1008 | } | 1042 | } |
1043 | |||
1044 | static const struct dev_pm_ops i8042_pm_ops = { | ||
1045 | .suspend = i8042_pm_reset, | ||
1046 | .resume = i8042_pm_restore, | ||
1047 | .poweroff = i8042_pm_reset, | ||
1048 | .restore = i8042_pm_restore, | ||
1049 | }; | ||
1050 | |||
1009 | #endif /* CONFIG_PM */ | 1051 | #endif /* CONFIG_PM */ |
1010 | 1052 | ||
1011 | /* | 1053 | /* |
@@ -1018,7 +1060,7 @@ static void i8042_shutdown(struct platform_device *dev) | |||
1018 | i8042_controller_reset(); | 1060 | i8042_controller_reset(); |
1019 | } | 1061 | } |
1020 | 1062 | ||
1021 | static int __devinit i8042_create_kbd_port(void) | 1063 | static int __init i8042_create_kbd_port(void) |
1022 | { | 1064 | { |
1023 | struct serio *serio; | 1065 | struct serio *serio; |
1024 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 1066 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
@@ -1031,6 +1073,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
1031 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 1073 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
1032 | serio->start = i8042_start; | 1074 | serio->start = i8042_start; |
1033 | serio->stop = i8042_stop; | 1075 | serio->stop = i8042_stop; |
1076 | serio->close = i8042_port_close; | ||
1034 | serio->port_data = port; | 1077 | serio->port_data = port; |
1035 | serio->dev.parent = &i8042_platform_device->dev; | 1078 | serio->dev.parent = &i8042_platform_device->dev; |
1036 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); | 1079 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
@@ -1042,7 +1085,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
1042 | return 0; | 1085 | return 0; |
1043 | } | 1086 | } |
1044 | 1087 | ||
1045 | static int __devinit i8042_create_aux_port(int idx) | 1088 | static int __init i8042_create_aux_port(int idx) |
1046 | { | 1089 | { |
1047 | struct serio *serio; | 1090 | struct serio *serio; |
1048 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; | 1091 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
@@ -1061,6 +1104,7 @@ static int __devinit i8042_create_aux_port(int idx) | |||
1061 | if (idx < 0) { | 1104 | if (idx < 0) { |
1062 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); | 1105 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
1063 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1106 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); |
1107 | serio->close = i8042_port_close; | ||
1064 | } else { | 1108 | } else { |
1065 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | 1109 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); |
1066 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | 1110 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); |
@@ -1073,13 +1117,13 @@ static int __devinit i8042_create_aux_port(int idx) | |||
1073 | return 0; | 1117 | return 0; |
1074 | } | 1118 | } |
1075 | 1119 | ||
1076 | static void __devinit i8042_free_kbd_port(void) | 1120 | static void __init i8042_free_kbd_port(void) |
1077 | { | 1121 | { |
1078 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); | 1122 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
1079 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; | 1123 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
1080 | } | 1124 | } |
1081 | 1125 | ||
1082 | static void __devinit i8042_free_aux_ports(void) | 1126 | static void __init i8042_free_aux_ports(void) |
1083 | { | 1127 | { |
1084 | int i; | 1128 | int i; |
1085 | 1129 | ||
@@ -1089,7 +1133,7 @@ static void __devinit i8042_free_aux_ports(void) | |||
1089 | } | 1133 | } |
1090 | } | 1134 | } |
1091 | 1135 | ||
1092 | static void __devinit i8042_register_ports(void) | 1136 | static void __init i8042_register_ports(void) |
1093 | { | 1137 | { |
1094 | int i; | 1138 | int i; |
1095 | 1139 | ||
@@ -1124,10 +1168,10 @@ static void i8042_free_irqs(void) | |||
1124 | if (i8042_kbd_irq_registered) | 1168 | if (i8042_kbd_irq_registered) |
1125 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | 1169 | free_irq(I8042_KBD_IRQ, i8042_platform_device); |
1126 | 1170 | ||
1127 | i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; | 1171 | i8042_aux_irq_registered = i8042_kbd_irq_registered = false; |
1128 | } | 1172 | } |
1129 | 1173 | ||
1130 | static int __devinit i8042_setup_aux(void) | 1174 | static int __init i8042_setup_aux(void) |
1131 | { | 1175 | { |
1132 | int (*aux_enable)(void); | 1176 | int (*aux_enable)(void); |
1133 | int error; | 1177 | int error; |
@@ -1158,7 +1202,7 @@ static int __devinit i8042_setup_aux(void) | |||
1158 | if (aux_enable()) | 1202 | if (aux_enable()) |
1159 | goto err_free_irq; | 1203 | goto err_free_irq; |
1160 | 1204 | ||
1161 | i8042_aux_irq_registered = 1; | 1205 | i8042_aux_irq_registered = true; |
1162 | return 0; | 1206 | return 0; |
1163 | 1207 | ||
1164 | err_free_irq: | 1208 | err_free_irq: |
@@ -1168,7 +1212,7 @@ static int __devinit i8042_setup_aux(void) | |||
1168 | return error; | 1212 | return error; |
1169 | } | 1213 | } |
1170 | 1214 | ||
1171 | static int __devinit i8042_setup_kbd(void) | 1215 | static int __init i8042_setup_kbd(void) |
1172 | { | 1216 | { |
1173 | int error; | 1217 | int error; |
1174 | 1218 | ||
@@ -1185,7 +1229,7 @@ static int __devinit i8042_setup_kbd(void) | |||
1185 | if (error) | 1229 | if (error) |
1186 | goto err_free_irq; | 1230 | goto err_free_irq; |
1187 | 1231 | ||
1188 | i8042_kbd_irq_registered = 1; | 1232 | i8042_kbd_irq_registered = true; |
1189 | return 0; | 1233 | return 0; |
1190 | 1234 | ||
1191 | err_free_irq: | 1235 | err_free_irq: |
@@ -1195,7 +1239,7 @@ static int __devinit i8042_setup_kbd(void) | |||
1195 | return error; | 1239 | return error; |
1196 | } | 1240 | } |
1197 | 1241 | ||
1198 | static int __devinit i8042_probe(struct platform_device *dev) | 1242 | static int __init i8042_probe(struct platform_device *dev) |
1199 | { | 1243 | { |
1200 | int error; | 1244 | int error; |
1201 | 1245 | ||
@@ -1251,14 +1295,12 @@ static struct platform_driver i8042_driver = { | |||
1251 | .driver = { | 1295 | .driver = { |
1252 | .name = "i8042", | 1296 | .name = "i8042", |
1253 | .owner = THIS_MODULE, | 1297 | .owner = THIS_MODULE, |
1298 | #ifdef CONFIG_PM | ||
1299 | .pm = &i8042_pm_ops, | ||
1300 | #endif | ||
1254 | }, | 1301 | }, |
1255 | .probe = i8042_probe, | ||
1256 | .remove = __devexit_p(i8042_remove), | 1302 | .remove = __devexit_p(i8042_remove), |
1257 | .shutdown = i8042_shutdown, | 1303 | .shutdown = i8042_shutdown, |
1258 | #ifdef CONFIG_PM | ||
1259 | .suspend = i8042_suspend, | ||
1260 | .resume = i8042_resume, | ||
1261 | #endif | ||
1262 | }; | 1304 | }; |
1263 | 1305 | ||
1264 | static int __init i8042_init(void) | 1306 | static int __init i8042_init(void) |
@@ -1275,28 +1317,28 @@ static int __init i8042_init(void) | |||
1275 | if (err) | 1317 | if (err) |
1276 | goto err_platform_exit; | 1318 | goto err_platform_exit; |
1277 | 1319 | ||
1278 | err = platform_driver_register(&i8042_driver); | ||
1279 | if (err) | ||
1280 | goto err_platform_exit; | ||
1281 | |||
1282 | i8042_platform_device = platform_device_alloc("i8042", -1); | 1320 | i8042_platform_device = platform_device_alloc("i8042", -1); |
1283 | if (!i8042_platform_device) { | 1321 | if (!i8042_platform_device) { |
1284 | err = -ENOMEM; | 1322 | err = -ENOMEM; |
1285 | goto err_unregister_driver; | 1323 | goto err_platform_exit; |
1286 | } | 1324 | } |
1287 | 1325 | ||
1288 | err = platform_device_add(i8042_platform_device); | 1326 | err = platform_device_add(i8042_platform_device); |
1289 | if (err) | 1327 | if (err) |
1290 | goto err_free_device; | 1328 | goto err_free_device; |
1291 | 1329 | ||
1330 | err = platform_driver_probe(&i8042_driver, i8042_probe); | ||
1331 | if (err) | ||
1332 | goto err_del_device; | ||
1333 | |||
1292 | panic_blink = i8042_panic_blink; | 1334 | panic_blink = i8042_panic_blink; |
1293 | 1335 | ||
1294 | return 0; | 1336 | return 0; |
1295 | 1337 | ||
1338 | err_del_device: | ||
1339 | platform_device_del(i8042_platform_device); | ||
1296 | err_free_device: | 1340 | err_free_device: |
1297 | platform_device_put(i8042_platform_device); | 1341 | platform_device_put(i8042_platform_device); |
1298 | err_unregister_driver: | ||
1299 | platform_driver_unregister(&i8042_driver); | ||
1300 | err_platform_exit: | 1342 | err_platform_exit: |
1301 | i8042_platform_exit(); | 1343 | i8042_platform_exit(); |
1302 | 1344 | ||
@@ -1305,8 +1347,8 @@ static int __init i8042_init(void) | |||
1305 | 1347 | ||
1306 | static void __exit i8042_exit(void) | 1348 | static void __exit i8042_exit(void) |
1307 | { | 1349 | { |
1308 | platform_device_unregister(i8042_platform_device); | ||
1309 | platform_driver_unregister(&i8042_driver); | 1350 | platform_driver_unregister(&i8042_driver); |
1351 | platform_device_unregister(i8042_platform_device); | ||
1310 | i8042_platform_exit(); | 1352 | i8042_platform_exit(); |
1311 | 1353 | ||
1312 | panic_blink = NULL; | 1354 | panic_blink = NULL; |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index be5bbbb8ae4e..3a95b508bf27 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -161,7 +161,7 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | |||
161 | * ps2_command() can only be called from a process context | 161 | * ps2_command() can only be called from a process context |
162 | */ | 162 | */ |
163 | 163 | ||
164 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | 164 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) |
165 | { | 165 | { |
166 | int timeout; | 166 | int timeout; |
167 | int send = (command >> 12) & 0xf; | 167 | int send = (command >> 12) & 0xf; |
@@ -179,8 +179,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
179 | return -1; | 179 | return -1; |
180 | } | 180 | } |
181 | 181 | ||
182 | mutex_lock(&ps2dev->cmd_mutex); | ||
183 | |||
184 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
185 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; | 183 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; |
186 | ps2dev->cmdcnt = receive; | 184 | ps2dev->cmdcnt = receive; |
@@ -231,7 +229,18 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
231 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
232 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
233 | 231 | ||
232 | return rc; | ||
233 | } | ||
234 | EXPORT_SYMBOL(__ps2_command); | ||
235 | |||
236 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | ||
237 | { | ||
238 | int rc; | ||
239 | |||
240 | mutex_lock(&ps2dev->cmd_mutex); | ||
241 | rc = __ps2_command(ps2dev, param, command); | ||
234 | mutex_unlock(&ps2dev->cmd_mutex); | 242 | mutex_unlock(&ps2dev->cmd_mutex); |
243 | |||
235 | return rc; | 244 | return rc; |
236 | } | 245 | } |
237 | EXPORT_SYMBOL(ps2_command); | 246 | EXPORT_SYMBOL(ps2_command); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index d66f4944f2a0..0236f0d5fd91 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -931,15 +931,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
931 | #endif /* CONFIG_HOTPLUG */ | 931 | #endif /* CONFIG_HOTPLUG */ |
932 | 932 | ||
933 | #ifdef CONFIG_PM | 933 | #ifdef CONFIG_PM |
934 | static int serio_suspend(struct device *dev, pm_message_t state) | 934 | static int serio_suspend(struct device *dev) |
935 | { | 935 | { |
936 | struct serio *serio = to_serio_port(dev); | 936 | struct serio *serio = to_serio_port(dev); |
937 | 937 | ||
938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) | 938 | serio_cleanup(serio); |
939 | serio_cleanup(serio); | ||
940 | |||
941 | serio->suspended = state.event == PM_EVENT_SUSPEND || | ||
942 | state.event == PM_EVENT_FREEZE; | ||
943 | 939 | ||
944 | return 0; | 940 | return 0; |
945 | } | 941 | } |
@@ -952,13 +948,17 @@ static int serio_resume(struct device *dev) | |||
952 | * Driver reconnect can take a while, so better let kseriod | 948 | * Driver reconnect can take a while, so better let kseriod |
953 | * deal with it. | 949 | * deal with it. |
954 | */ | 950 | */ |
955 | if (serio->suspended) { | 951 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
956 | serio->suspended = false; | ||
957 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); | ||
958 | } | ||
959 | 952 | ||
960 | return 0; | 953 | return 0; |
961 | } | 954 | } |
955 | |||
956 | static const struct dev_pm_ops serio_pm_ops = { | ||
957 | .suspend = serio_suspend, | ||
958 | .resume = serio_resume, | ||
959 | .poweroff = serio_suspend, | ||
960 | .restore = serio_resume, | ||
961 | }; | ||
962 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
963 | 963 | ||
964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ | 964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ |
@@ -1015,8 +1015,7 @@ static struct bus_type serio_bus = { | |||
1015 | .remove = serio_driver_remove, | 1015 | .remove = serio_driver_remove, |
1016 | .shutdown = serio_shutdown, | 1016 | .shutdown = serio_shutdown, |
1017 | #ifdef CONFIG_PM | 1017 | #ifdef CONFIG_PM |
1018 | .suspend = serio_suspend, | 1018 | .pm = &serio_pm_ops, |
1019 | .resume = serio_resume, | ||
1020 | #endif | 1019 | #endif |
1021 | }; | 1020 | }; |
1022 | 1021 | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712c7e2a..87a1ae63bcc4 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -366,11 +366,11 @@ config TOUCHSCREEN_WM97XX_ATMEL | |||
366 | be called atmel-wm97xx. | 366 | be called atmel-wm97xx. |
367 | 367 | ||
368 | config TOUCHSCREEN_WM97XX_MAINSTONE | 368 | config TOUCHSCREEN_WM97XX_MAINSTONE |
369 | tristate "WM97xx Mainstone accelerated touch" | 369 | tristate "WM97xx Mainstone/Palm accelerated touch" |
370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA | 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA |
371 | help | 371 | help |
372 | Say Y here for support for streaming mode with WM97xx touchscreens | 372 | Say Y here for support for streaming mode with WM97xx touchscreens |
373 | on Mainstone systems. | 373 | on Mainstone, Palm Tungsten T5, TX and LifeDrive systems. |
374 | 374 | ||
375 | If unsure, say N. | 375 | If unsure, say N. |
376 | 376 | ||
@@ -406,6 +406,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
406 | - IRTOUCHSYSTEMS/UNITOP | 406 | - IRTOUCHSYSTEMS/UNITOP |
407 | - IdealTEK URTC1000 | 407 | - IdealTEK URTC1000 |
408 | - GoTop Super_Q2/GogoPen/PenPower tablets | 408 | - GoTop Super_Q2/GogoPen/PenPower tablets |
409 | - JASTEC USB Touch Controller/DigiTech DTR-02U | ||
409 | 410 | ||
410 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 411 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
411 | a usage description and the required user-space stuff. | 412 | a usage description and the required user-space stuff. |
@@ -468,6 +469,16 @@ config TOUCHSCREEN_USB_GOTOP | |||
468 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED | 469 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED |
469 | depends on TOUCHSCREEN_USB_COMPOSITE | 470 | depends on TOUCHSCREEN_USB_COMPOSITE |
470 | 471 | ||
472 | config TOUCHSCREEN_USB_JASTEC | ||
473 | default y | ||
474 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED | ||
475 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
476 | |||
477 | config TOUCHSCREEN_USB_E2I | ||
478 | default y | ||
479 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | ||
480 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
481 | |||
471 | config TOUCHSCREEN_TOUCHIT213 | 482 | config TOUCHSCREEN_TOUCHIT213 |
472 | tristate "Sahara TouchIT-213 touchscreen" | 483 | tristate "Sahara TouchIT-213 touchscreen" |
473 | select SERIO | 484 | select SERIO |
@@ -492,6 +503,7 @@ config TOUCHSCREEN_TSC2007 | |||
492 | 503 | ||
493 | config TOUCHSCREEN_W90X900 | 504 | config TOUCHSCREEN_W90X900 |
494 | tristate "W90P910 touchscreen driver" | 505 | tristate "W90P910 touchscreen driver" |
506 | depends on HAVE_CLK | ||
495 | help | 507 | help |
496 | Say Y here if you have a W90P910 based touchscreen. | 508 | Say Y here if you have a W90P910 based touchscreen. |
497 | 509 | ||
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 055969e8be13..9c7fce4d74d0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -204,14 +204,14 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
204 | goto err_free_dev; | 204 | goto err_free_dev; |
205 | } | 205 | } |
206 | 206 | ||
207 | if (!request_mem_region(res->start, res->end - res->start + 1, | 207 | if (!request_mem_region(res->start, resource_size(res), |
208 | "atmel tsadcc regs")) { | 208 | "atmel tsadcc regs")) { |
209 | dev_err(&pdev->dev, "resources is unavailable.\n"); | 209 | dev_err(&pdev->dev, "resources is unavailable.\n"); |
210 | err = -EBUSY; | 210 | err = -EBUSY; |
211 | goto err_free_dev; | 211 | goto err_free_dev; |
212 | } | 212 | } |
213 | 213 | ||
214 | tsc_base = ioremap(res->start, res->end - res->start + 1); | 214 | tsc_base = ioremap(res->start, resource_size(res)); |
215 | if (!tsc_base) { | 215 | if (!tsc_base) { |
216 | dev_err(&pdev->dev, "failed to map registers.\n"); | 216 | dev_err(&pdev->dev, "failed to map registers.\n"); |
217 | err = -ENOMEM; | 217 | err = -ENOMEM; |
@@ -286,7 +286,7 @@ err_free_irq: | |||
286 | err_unmap_regs: | 286 | err_unmap_regs: |
287 | iounmap(tsc_base); | 287 | iounmap(tsc_base); |
288 | err_release_mem: | 288 | err_release_mem: |
289 | release_mem_region(res->start, res->end - res->start + 1); | 289 | release_mem_region(res->start, resource_size(res)); |
290 | err_free_dev: | 290 | err_free_dev: |
291 | input_free_device(ts_dev->input); | 291 | input_free_device(ts_dev->input); |
292 | err_free_mem: | 292 | err_free_mem: |
@@ -305,7 +305,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) | |||
305 | 305 | ||
306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
307 | iounmap(tsc_base); | 307 | iounmap(tsc_base); |
308 | release_mem_region(res->start, res->end - res->start + 1); | 308 | release_mem_region(res->start, resource_size(res)); |
309 | 309 | ||
310 | clk_disable(ts_dev->clk); | 310 | clk_disable(ts_dev->clk); |
311 | clk_put(ts_dev->clk); | 311 | clk_put(ts_dev->clk); |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 3ab92222a525..9029bd3f34e5 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
35 | #include <linux/input/eeti_ts.h> | ||
35 | 36 | ||
36 | static int flip_x; | 37 | static int flip_x; |
37 | module_param(flip_x, bool, 0644); | 38 | module_param(flip_x, bool, 0644); |
@@ -46,7 +47,7 @@ struct eeti_ts_priv { | |||
46 | struct input_dev *input; | 47 | struct input_dev *input; |
47 | struct work_struct work; | 48 | struct work_struct work; |
48 | struct mutex mutex; | 49 | struct mutex mutex; |
49 | int irq; | 50 | int irq, irq_active_high; |
50 | }; | 51 | }; |
51 | 52 | ||
52 | #define EETI_TS_BITDEPTH (11) | 53 | #define EETI_TS_BITDEPTH (11) |
@@ -58,6 +59,11 @@ struct eeti_ts_priv { | |||
58 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) | 59 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) |
59 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) | 60 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) |
60 | 61 | ||
62 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) | ||
63 | { | ||
64 | return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; | ||
65 | } | ||
66 | |||
61 | static void eeti_ts_read(struct work_struct *work) | 67 | static void eeti_ts_read(struct work_struct *work) |
62 | { | 68 | { |
63 | char buf[6]; | 69 | char buf[6]; |
@@ -67,7 +73,7 @@ static void eeti_ts_read(struct work_struct *work) | |||
67 | 73 | ||
68 | mutex_lock(&priv->mutex); | 74 | mutex_lock(&priv->mutex); |
69 | 75 | ||
70 | while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to) | 76 | while (eeti_ts_irq_active(priv) && --to) |
71 | i2c_master_recv(priv->client, buf, sizeof(buf)); | 77 | i2c_master_recv(priv->client, buf, sizeof(buf)); |
72 | 78 | ||
73 | if (!to) { | 79 | if (!to) { |
@@ -140,8 +146,10 @@ static void eeti_ts_close(struct input_dev *dev) | |||
140 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 146 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
141 | const struct i2c_device_id *idp) | 147 | const struct i2c_device_id *idp) |
142 | { | 148 | { |
149 | struct eeti_ts_platform_data *pdata; | ||
143 | struct eeti_ts_priv *priv; | 150 | struct eeti_ts_priv *priv; |
144 | struct input_dev *input; | 151 | struct input_dev *input; |
152 | unsigned int irq_flags; | ||
145 | int err = -ENOMEM; | 153 | int err = -ENOMEM; |
146 | 154 | ||
147 | /* In contrast to what's described in the datasheet, there seems | 155 | /* In contrast to what's described in the datasheet, there seems |
@@ -180,6 +188,14 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
180 | priv->input = input; | 188 | priv->input = input; |
181 | priv->irq = client->irq; | 189 | priv->irq = client->irq; |
182 | 190 | ||
191 | pdata = client->dev.platform_data; | ||
192 | |||
193 | if (pdata) | ||
194 | priv->irq_active_high = pdata->irq_active_high; | ||
195 | |||
196 | irq_flags = priv->irq_active_high ? | ||
197 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | ||
198 | |||
183 | INIT_WORK(&priv->work, eeti_ts_read); | 199 | INIT_WORK(&priv->work, eeti_ts_read); |
184 | i2c_set_clientdata(client, priv); | 200 | i2c_set_clientdata(client, priv); |
185 | input_set_drvdata(input, priv); | 201 | input_set_drvdata(input, priv); |
@@ -188,7 +204,7 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
188 | if (err) | 204 | if (err) |
189 | goto err1; | 205 | goto err1; |
190 | 206 | ||
191 | err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING, | 207 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, |
192 | client->name, priv); | 208 | client->name, priv); |
193 | if (err) { | 209 | if (err) { |
194 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 210 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 4d3139e2099d..b4d7f63deff1 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -148,9 +148,10 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
148 | struct h3600_dev *ts = input_get_drvdata(dev); | 148 | struct h3600_dev *ts = input_get_drvdata(dev); |
149 | 149 | ||
150 | /* Must be in this order */ | 150 | /* Must be in this order */ |
151 | ts->serio->write(ts->serio, 1); | 151 | serio_write(ts->serio, 1); |
152 | ts->serio->write(ts->serio, pwr); | 152 | serio_write(ts->serio, pwr); |
153 | ts->serio->write(ts->serio, brightness); | 153 | serio_write(ts->serio, brightness); |
154 | |||
154 | return 0; | 155 | return 0; |
155 | } | 156 | } |
156 | 157 | ||
@@ -262,7 +263,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, | |||
262 | 263 | ||
263 | switch (type) { | 264 | switch (type) { |
264 | case EV_LED: { | 265 | case EV_LED: { |
265 | // ts->serio->write(ts->serio, SOME_CMD); | 266 | // serio_write(ts->serio, SOME_CMD); |
266 | return 0; | 267 | return 0; |
267 | } | 268 | } |
268 | } | 269 | } |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 4cc047a5116e..8fc3b08deb3b 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -31,9 +31,11 @@ | |||
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/wm97xx.h> | 32 | #include <linux/wm97xx.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/gpio.h> | ||
35 | |||
34 | #include <mach/regs-ac97.h> | 36 | #include <mach/regs-ac97.h> |
35 | 37 | ||
36 | #define VERSION "0.13" | 38 | #include <asm/mach-types.h> |
37 | 39 | ||
38 | struct continuous { | 40 | struct continuous { |
39 | u16 id; /* codec id */ | 41 | u16 id; /* codec id */ |
@@ -62,6 +64,7 @@ static const struct continuous cinfo[] = { | |||
62 | /* continuous speed index */ | 64 | /* continuous speed index */ |
63 | static int sp_idx; | 65 | static int sp_idx; |
64 | static u16 last, tries; | 66 | static u16 last, tries; |
67 | static int irq; | ||
65 | 68 | ||
66 | /* | 69 | /* |
67 | * Pen sampling frequency (Hz) in continuous mode. | 70 | * Pen sampling frequency (Hz) in continuous mode. |
@@ -171,7 +174,7 @@ up: | |||
171 | 174 | ||
172 | static int wm97xx_acc_startup(struct wm97xx *wm) | 175 | static int wm97xx_acc_startup(struct wm97xx *wm) |
173 | { | 176 | { |
174 | int idx = 0; | 177 | int idx = 0, ret = 0; |
175 | 178 | ||
176 | /* check we have a codec */ | 179 | /* check we have a codec */ |
177 | if (wm->ac97 == NULL) | 180 | if (wm->ac97 == NULL) |
@@ -191,18 +194,40 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
191 | "mainstone accelerated touchscreen driver, %d samples/sec\n", | 194 | "mainstone accelerated touchscreen driver, %d samples/sec\n", |
192 | cinfo[sp_idx].speed); | 195 | cinfo[sp_idx].speed); |
193 | 196 | ||
197 | /* IRQ driven touchscreen is used on Palm hardware */ | ||
198 | if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) { | ||
199 | pen_int = 1; | ||
200 | irq = 27; | ||
201 | /* There is some obscure mutant of WM9712 interbred with WM9713 | ||
202 | * used on Palm HW */ | ||
203 | wm->variant = WM97xx_WM1613; | ||
204 | } else if (machine_is_mainstone() && pen_int) | ||
205 | irq = 4; | ||
206 | |||
207 | if (irq) { | ||
208 | ret = gpio_request(irq, "Touchscreen IRQ"); | ||
209 | if (ret) | ||
210 | goto out; | ||
211 | |||
212 | ret = gpio_direction_input(irq); | ||
213 | if (ret) { | ||
214 | gpio_free(irq); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | wm->pen_irq = gpio_to_irq(irq); | ||
219 | set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | ||
220 | } else /* pen irq not supported */ | ||
221 | pen_int = 0; | ||
222 | |||
194 | /* codec specific irq config */ | 223 | /* codec specific irq config */ |
195 | if (pen_int) { | 224 | if (pen_int) { |
196 | switch (wm->id) { | 225 | switch (wm->id) { |
197 | case WM9705_ID2: | 226 | case WM9705_ID2: |
198 | wm->pen_irq = IRQ_GPIO(4); | ||
199 | set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH); | ||
200 | break; | 227 | break; |
201 | case WM9712_ID2: | 228 | case WM9712_ID2: |
202 | case WM9713_ID2: | 229 | case WM9713_ID2: |
203 | /* enable pen down interrupt */ | ||
204 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ | 230 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ |
205 | wm->pen_irq = MAINSTONE_AC97_IRQ; | ||
206 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 231 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
207 | WM97XX_GPIO_POL_HIGH, | 232 | WM97XX_GPIO_POL_HIGH, |
208 | WM97XX_GPIO_STICKY, | 233 | WM97XX_GPIO_STICKY, |
@@ -220,23 +245,17 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
220 | } | 245 | } |
221 | } | 246 | } |
222 | 247 | ||
223 | return 0; | 248 | out: |
249 | return ret; | ||
224 | } | 250 | } |
225 | 251 | ||
226 | static void wm97xx_acc_shutdown(struct wm97xx *wm) | 252 | static void wm97xx_acc_shutdown(struct wm97xx *wm) |
227 | { | 253 | { |
228 | /* codec specific deconfig */ | 254 | /* codec specific deconfig */ |
229 | if (pen_int) { | 255 | if (pen_int) { |
230 | switch (wm->id & 0xffff) { | 256 | if (irq) |
231 | case WM9705_ID2: | 257 | gpio_free(irq); |
232 | wm->pen_irq = 0; | 258 | wm->pen_irq = 0; |
233 | break; | ||
234 | case WM9712_ID2: | ||
235 | case WM9713_ID2: | ||
236 | /* disable interrupt */ | ||
237 | wm->pen_irq = 0; | ||
238 | break; | ||
239 | } | ||
240 | } | 259 | } |
241 | } | 260 | } |
242 | 261 | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 880f58c6a7c4..7ef0d1420d3c 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -21,15 +21,14 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
29 | #include <linux/i2c/tsc2007.h> | 28 | #include <linux/i2c/tsc2007.h> |
30 | 29 | ||
31 | #define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */ | 30 | #define TS_POLL_DELAY 1 /* ms delay between samples */ |
32 | #define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */ | 31 | #define TS_POLL_PERIOD 1 /* ms delay between samples */ |
33 | 32 | ||
34 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) | 33 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) |
35 | #define TSC2007_MEASURE_AUX (0x2 << 4) | 34 | #define TSC2007_MEASURE_AUX (0x2 << 4) |
@@ -70,17 +69,14 @@ struct ts_event { | |||
70 | struct tsc2007 { | 69 | struct tsc2007 { |
71 | struct input_dev *input; | 70 | struct input_dev *input; |
72 | char phys[32]; | 71 | char phys[32]; |
73 | struct hrtimer timer; | 72 | struct delayed_work work; |
74 | struct ts_event tc; | ||
75 | 73 | ||
76 | struct i2c_client *client; | 74 | struct i2c_client *client; |
77 | 75 | ||
78 | spinlock_t lock; | ||
79 | |||
80 | u16 model; | 76 | u16 model; |
81 | u16 x_plate_ohms; | 77 | u16 x_plate_ohms; |
82 | 78 | ||
83 | unsigned pendown; | 79 | bool pendown; |
84 | int irq; | 80 | int irq; |
85 | 81 | ||
86 | int (*get_pendown_state)(void); | 82 | int (*get_pendown_state)(void); |
@@ -109,52 +105,96 @@ static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) | |||
109 | return val; | 105 | return val; |
110 | } | 106 | } |
111 | 107 | ||
112 | static void tsc2007_send_event(void *tsc) | 108 | static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) |
113 | { | 109 | { |
114 | struct tsc2007 *ts = tsc; | 110 | /* y- still on; turn on only y+ (and ADC) */ |
115 | u32 rt; | 111 | tc->y = tsc2007_xfer(tsc, READ_Y); |
116 | u16 x, y, z1, z2; | 112 | |
113 | /* turn y- off, x+ on, then leave in lowpower */ | ||
114 | tc->x = tsc2007_xfer(tsc, READ_X); | ||
115 | |||
116 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
117 | tc->z1 = tsc2007_xfer(tsc, READ_Z1); | ||
118 | tc->z2 = tsc2007_xfer(tsc, READ_Z2); | ||
117 | 119 | ||
118 | x = ts->tc.x; | 120 | /* Prepare for next touch reading - power down ADC, enable PENIRQ */ |
119 | y = ts->tc.y; | 121 | tsc2007_xfer(tsc, PWRDOWN); |
120 | z1 = ts->tc.z1; | 122 | } |
121 | z2 = ts->tc.z2; | 123 | |
124 | static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | ||
125 | { | ||
126 | u32 rt = 0; | ||
122 | 127 | ||
123 | /* range filtering */ | 128 | /* range filtering */ |
124 | if (x == MAX_12BIT) | 129 | if (tc->x == MAX_12BIT) |
125 | x = 0; | 130 | tc->x = 0; |
126 | 131 | ||
127 | if (likely(x && z1)) { | 132 | if (likely(tc->x && tc->z1)) { |
128 | /* compute touch pressure resistance using equation #1 */ | 133 | /* compute touch pressure resistance using equation #1 */ |
129 | rt = z2; | 134 | rt = tc->z2 - tc->z1; |
130 | rt -= z1; | 135 | rt *= tc->x; |
131 | rt *= x; | 136 | rt *= tsc->x_plate_ohms; |
132 | rt *= ts->x_plate_ohms; | 137 | rt /= tc->z1; |
133 | rt /= z1; | ||
134 | rt = (rt + 2047) >> 12; | 138 | rt = (rt + 2047) >> 12; |
135 | } else | 139 | } |
136 | rt = 0; | 140 | |
141 | return rt; | ||
142 | } | ||
143 | |||
144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) | ||
145 | { | ||
146 | struct input_dev *input = tsc->input; | ||
137 | 147 | ||
138 | /* Sample found inconsistent by debouncing or pressure is beyond | 148 | dev_dbg(&tsc->client->dev, "UP\n"); |
139 | * the maximum. Don't report it to user space, repeat at least | 149 | |
140 | * once more the measurement | 150 | input_report_key(input, BTN_TOUCH, 0); |
151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
152 | input_sync(input); | ||
153 | } | ||
154 | |||
155 | static void tsc2007_work(struct work_struct *work) | ||
156 | { | ||
157 | struct tsc2007 *ts = | ||
158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
159 | struct ts_event tc; | ||
160 | u32 rt; | ||
161 | |||
162 | /* | ||
163 | * NOTE: We can't rely on the pressure to determine the pen down | ||
164 | * state, even though this controller has a pressure sensor. | ||
165 | * The pressure value can fluctuate for quite a while after | ||
166 | * lifting the pen and in some cases may not even settle at the | ||
167 | * expected value. | ||
168 | * | ||
169 | * The only safe way to check for the pen up condition is in the | ||
170 | * work function by reading the pen signal state (it's a GPIO | ||
171 | * and IRQ). Unfortunately such callback is not always available, | ||
172 | * in that case we have rely on the pressure anyway. | ||
141 | */ | 173 | */ |
174 | if (ts->get_pendown_state) { | ||
175 | if (unlikely(!ts->get_pendown_state())) { | ||
176 | tsc2007_send_up_event(ts); | ||
177 | ts->pendown = false; | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
182 | } | ||
183 | |||
184 | tsc2007_read_values(ts, &tc); | ||
185 | |||
186 | rt = tsc2007_calculate_pressure(ts, &tc); | ||
142 | if (rt > MAX_12BIT) { | 187 | if (rt > MAX_12BIT) { |
188 | /* | ||
189 | * Sample found inconsistent by debouncing or pressure is | ||
190 | * beyond the maximum. Don't report it to user space, | ||
191 | * repeat at least once more the measurement. | ||
192 | */ | ||
143 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 193 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
194 | goto out; | ||
144 | 195 | ||
145 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | ||
146 | HRTIMER_MODE_REL); | ||
147 | return; | ||
148 | } | 196 | } |
149 | 197 | ||
150 | /* NOTE: We can't rely on the pressure to determine the pen down | ||
151 | * state, even this controller has a pressure sensor. The pressure | ||
152 | * value can fluctuate for quite a while after lifting the pen and | ||
153 | * in some cases may not even settle at the expected value. | ||
154 | * | ||
155 | * The only safe way to check for the pen up condition is in the | ||
156 | * timer by reading the pen signal state (it's a GPIO _and_ IRQ). | ||
157 | */ | ||
158 | if (rt) { | 198 | if (rt) { |
159 | struct input_dev *input = ts->input; | 199 | struct input_dev *input = ts->input; |
160 | 200 | ||
@@ -162,102 +202,74 @@ static void tsc2007_send_event(void *tsc) | |||
162 | dev_dbg(&ts->client->dev, "DOWN\n"); | 202 | dev_dbg(&ts->client->dev, "DOWN\n"); |
163 | 203 | ||
164 | input_report_key(input, BTN_TOUCH, 1); | 204 | input_report_key(input, BTN_TOUCH, 1); |
165 | ts->pendown = 1; | 205 | ts->pendown = true; |
166 | } | 206 | } |
167 | 207 | ||
168 | input_report_abs(input, ABS_X, x); | 208 | input_report_abs(input, ABS_X, tc.x); |
169 | input_report_abs(input, ABS_Y, y); | 209 | input_report_abs(input, ABS_Y, tc.y); |
170 | input_report_abs(input, ABS_PRESSURE, rt); | 210 | input_report_abs(input, ABS_PRESSURE, rt); |
171 | 211 | ||
172 | input_sync(input); | 212 | input_sync(input); |
173 | 213 | ||
174 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", | 214 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", |
175 | x, y, rt); | 215 | tc.x, tc.y, rt); |
216 | |||
217 | } else if (!ts->get_pendown_state && ts->pendown) { | ||
218 | /* | ||
219 | * We don't have callback to check pendown state, so we | ||
220 | * have to assume that since pressure reported is 0 the | ||
221 | * pen was lifted up. | ||
222 | */ | ||
223 | tsc2007_send_up_event(ts); | ||
224 | ts->pendown = false; | ||
176 | } | 225 | } |
177 | 226 | ||
178 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 227 | out: |
179 | HRTIMER_MODE_REL); | 228 | if (ts->pendown) |
180 | } | 229 | schedule_delayed_work(&ts->work, |
181 | 230 | msecs_to_jiffies(TS_POLL_PERIOD)); | |
182 | static int tsc2007_read_values(struct tsc2007 *tsc) | 231 | else |
183 | { | ||
184 | /* y- still on; turn on only y+ (and ADC) */ | ||
185 | tsc->tc.y = tsc2007_xfer(tsc, READ_Y); | ||
186 | |||
187 | /* turn y- off, x+ on, then leave in lowpower */ | ||
188 | tsc->tc.x = tsc2007_xfer(tsc, READ_X); | ||
189 | |||
190 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
191 | tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1); | ||
192 | tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2); | ||
193 | |||
194 | /* power down */ | ||
195 | tsc2007_xfer(tsc, PWRDOWN); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) | ||
201 | { | ||
202 | struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&ts->lock, flags); | ||
206 | |||
207 | if (unlikely(!ts->get_pendown_state() && ts->pendown)) { | ||
208 | struct input_dev *input = ts->input; | ||
209 | |||
210 | dev_dbg(&ts->client->dev, "UP\n"); | ||
211 | |||
212 | input_report_key(input, BTN_TOUCH, 0); | ||
213 | input_report_abs(input, ABS_PRESSURE, 0); | ||
214 | input_sync(input); | ||
215 | |||
216 | ts->pendown = 0; | ||
217 | enable_irq(ts->irq); | 232 | enable_irq(ts->irq); |
218 | } else { | ||
219 | /* pen is still down, continue with the measurement */ | ||
220 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
221 | |||
222 | tsc2007_read_values(ts); | ||
223 | tsc2007_send_event(ts); | ||
224 | } | ||
225 | |||
226 | spin_unlock_irqrestore(&ts->lock, flags); | ||
227 | |||
228 | return HRTIMER_NORESTART; | ||
229 | } | 233 | } |
230 | 234 | ||
231 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 235 | static irqreturn_t tsc2007_irq(int irq, void *handle) |
232 | { | 236 | { |
233 | struct tsc2007 *ts = handle; | 237 | struct tsc2007 *ts = handle; |
234 | unsigned long flags; | ||
235 | |||
236 | spin_lock_irqsave(&ts->lock, flags); | ||
237 | 238 | ||
238 | if (likely(ts->get_pendown_state())) { | 239 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { |
239 | disable_irq_nosync(ts->irq); | 240 | disable_irq_nosync(ts->irq); |
240 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 241 | schedule_delayed_work(&ts->work, |
241 | HRTIMER_MODE_REL); | 242 | msecs_to_jiffies(TS_POLL_DELAY)); |
242 | } | 243 | } |
243 | 244 | ||
244 | if (ts->clear_penirq) | 245 | if (ts->clear_penirq) |
245 | ts->clear_penirq(); | 246 | ts->clear_penirq(); |
246 | 247 | ||
247 | spin_unlock_irqrestore(&ts->lock, flags); | ||
248 | |||
249 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
250 | } | 249 | } |
251 | 250 | ||
252 | static int tsc2007_probe(struct i2c_client *client, | 251 | static void tsc2007_free_irq(struct tsc2007 *ts) |
253 | const struct i2c_device_id *id) | 252 | { |
253 | free_irq(ts->irq, ts); | ||
254 | if (cancel_delayed_work_sync(&ts->work)) { | ||
255 | /* | ||
256 | * Work was pending, therefore we need to enable | ||
257 | * IRQ here to balance the disable_irq() done in the | ||
258 | * interrupt handler. | ||
259 | */ | ||
260 | enable_irq(ts->irq); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static int __devinit tsc2007_probe(struct i2c_client *client, | ||
265 | const struct i2c_device_id *id) | ||
254 | { | 266 | { |
255 | struct tsc2007 *ts; | 267 | struct tsc2007 *ts; |
256 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; | 268 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; |
257 | struct input_dev *input_dev; | 269 | struct input_dev *input_dev; |
258 | int err; | 270 | int err; |
259 | 271 | ||
260 | if (!pdata || !pdata->get_pendown_state) { | 272 | if (!pdata) { |
261 | dev_err(&client->dev, "platform data is required!\n"); | 273 | dev_err(&client->dev, "platform data is required!\n"); |
262 | return -EINVAL; | 274 | return -EINVAL; |
263 | } | 275 | } |
@@ -274,22 +286,15 @@ static int tsc2007_probe(struct i2c_client *client, | |||
274 | } | 286 | } |
275 | 287 | ||
276 | ts->client = client; | 288 | ts->client = client; |
277 | i2c_set_clientdata(client, ts); | 289 | ts->irq = client->irq; |
278 | |||
279 | ts->input = input_dev; | 290 | ts->input = input_dev; |
280 | 291 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); | |
281 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
282 | ts->timer.function = tsc2007_timer; | ||
283 | |||
284 | spin_lock_init(&ts->lock); | ||
285 | 292 | ||
286 | ts->model = pdata->model; | 293 | ts->model = pdata->model; |
287 | ts->x_plate_ohms = pdata->x_plate_ohms; | 294 | ts->x_plate_ohms = pdata->x_plate_ohms; |
288 | ts->get_pendown_state = pdata->get_pendown_state; | 295 | ts->get_pendown_state = pdata->get_pendown_state; |
289 | ts->clear_penirq = pdata->clear_penirq; | 296 | ts->clear_penirq = pdata->clear_penirq; |
290 | 297 | ||
291 | pdata->init_platform_hw(); | ||
292 | |||
293 | snprintf(ts->phys, sizeof(ts->phys), | 298 | snprintf(ts->phys, sizeof(ts->phys), |
294 | "%s/input0", dev_name(&client->dev)); | 299 | "%s/input0", dev_name(&client->dev)); |
295 | 300 | ||
@@ -304,9 +309,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
304 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | 309 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
305 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | 310 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); |
306 | 311 | ||
307 | tsc2007_read_values(ts); | 312 | if (pdata->init_platform_hw) |
308 | 313 | pdata->init_platform_hw(); | |
309 | ts->irq = client->irq; | ||
310 | 314 | ||
311 | err = request_irq(ts->irq, tsc2007_irq, 0, | 315 | err = request_irq(ts->irq, tsc2007_irq, 0, |
312 | client->dev.driver->name, ts); | 316 | client->dev.driver->name, ts); |
@@ -315,33 +319,39 @@ static int tsc2007_probe(struct i2c_client *client, | |||
315 | goto err_free_mem; | 319 | goto err_free_mem; |
316 | } | 320 | } |
317 | 321 | ||
322 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
323 | err = tsc2007_xfer(ts, PWRDOWN); | ||
324 | if (err < 0) | ||
325 | goto err_free_irq; | ||
326 | |||
318 | err = input_register_device(input_dev); | 327 | err = input_register_device(input_dev); |
319 | if (err) | 328 | if (err) |
320 | goto err_free_irq; | 329 | goto err_free_irq; |
321 | 330 | ||
322 | dev_info(&client->dev, "registered with irq (%d)\n", ts->irq); | 331 | i2c_set_clientdata(client, ts); |
323 | 332 | ||
324 | return 0; | 333 | return 0; |
325 | 334 | ||
326 | err_free_irq: | 335 | err_free_irq: |
327 | free_irq(ts->irq, ts); | 336 | tsc2007_free_irq(ts); |
328 | hrtimer_cancel(&ts->timer); | 337 | if (pdata->exit_platform_hw) |
338 | pdata->exit_platform_hw(); | ||
329 | err_free_mem: | 339 | err_free_mem: |
330 | input_free_device(input_dev); | 340 | input_free_device(input_dev); |
331 | kfree(ts); | 341 | kfree(ts); |
332 | return err; | 342 | return err; |
333 | } | 343 | } |
334 | 344 | ||
335 | static int tsc2007_remove(struct i2c_client *client) | 345 | static int __devexit tsc2007_remove(struct i2c_client *client) |
336 | { | 346 | { |
337 | struct tsc2007 *ts = i2c_get_clientdata(client); | 347 | struct tsc2007 *ts = i2c_get_clientdata(client); |
338 | struct tsc2007_platform_data *pdata; | 348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
339 | 349 | ||
340 | pdata = client->dev.platform_data; | 350 | tsc2007_free_irq(ts); |
341 | pdata->exit_platform_hw(); | 351 | |
352 | if (pdata->exit_platform_hw) | ||
353 | pdata->exit_platform_hw(); | ||
342 | 354 | ||
343 | free_irq(ts->irq, ts); | ||
344 | hrtimer_cancel(&ts->timer); | ||
345 | input_unregister_device(ts->input); | 355 | input_unregister_device(ts->input); |
346 | kfree(ts); | 356 | kfree(ts); |
347 | 357 | ||
@@ -362,7 +372,7 @@ static struct i2c_driver tsc2007_driver = { | |||
362 | }, | 372 | }, |
363 | .id_table = tsc2007_idtable, | 373 | .id_table = tsc2007_idtable, |
364 | .probe = tsc2007_probe, | 374 | .probe = tsc2007_probe, |
365 | .remove = tsc2007_remove, | 375 | .remove = __devexit_p(tsc2007_remove), |
366 | }; | 376 | }; |
367 | 377 | ||
368 | static int __init tsc2007_init(void) | 378 | static int __init tsc2007_init(void) |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 3a7a58222f83..095f84b1f56e 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -128,9 +128,10 @@ static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | |||
128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); | 128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline int ucb1400_ts_pen_down(struct snd_ac97 *ac97) | 131 | static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97) |
132 | { | 132 | { |
133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); | 133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); |
134 | |||
134 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); | 135 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); |
135 | } | 136 | } |
136 | 137 | ||
@@ -209,7 +210,7 @@ static int ucb1400_ts_thread(void *_ucb) | |||
209 | 210 | ||
210 | msleep(10); | 211 | msleep(10); |
211 | 212 | ||
212 | if (ucb1400_ts_pen_down(ucb->ac97)) { | 213 | if (ucb1400_ts_pen_up(ucb->ac97)) { |
213 | ucb1400_ts_irq_enable(ucb->ac97); | 214 | ucb1400_ts_irq_enable(ucb->ac97); |
214 | 215 | ||
215 | /* | 216 | /* |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index fb7cb9bdfbd5..68ece5801a58 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * - IdealTEK URTC1000 | 13 | * - IdealTEK URTC1000 |
14 | * - General Touch | 14 | * - General Touch |
15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
16 | * - JASTEC USB touch controller/DigiTech DTR-02U | ||
16 | * | 17 | * |
17 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
18 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -118,6 +119,8 @@ enum { | |||
118 | DEVTYPE_IDEALTEK, | 119 | DEVTYPE_IDEALTEK, |
119 | DEVTYPE_GENERAL_TOUCH, | 120 | DEVTYPE_GENERAL_TOUCH, |
120 | DEVTYPE_GOTOP, | 121 | DEVTYPE_GOTOP, |
122 | DEVTYPE_JASTEC, | ||
123 | DEVTYPE_E2I, | ||
121 | }; | 124 | }; |
122 | 125 | ||
123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
@@ -191,11 +194,51 @@ static struct usb_device_id usbtouch_devices[] = { | |||
191 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 194 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, |
192 | #endif | 195 | #endif |
193 | 196 | ||
197 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
198 | {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, | ||
199 | #endif | ||
200 | |||
201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | ||
203 | #endif | ||
194 | {} | 204 | {} |
195 | }; | 205 | }; |
196 | 206 | ||
197 | 207 | ||
198 | /***************************************************************************** | 208 | /***************************************************************************** |
209 | * e2i Part | ||
210 | */ | ||
211 | |||
212 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
213 | static int e2i_init(struct usbtouch_usb *usbtouch) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
218 | 0x01, 0x02, 0x0000, 0x0081, | ||
219 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
220 | |||
221 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", | ||
222 | __func__, ret); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
227 | { | ||
228 | int tmp = (pkt[0] << 8) | pkt[1]; | ||
229 | dev->x = (pkt[2] << 8) | pkt[3]; | ||
230 | dev->y = (pkt[4] << 8) | pkt[5]; | ||
231 | |||
232 | tmp = tmp - 0xA000; | ||
233 | dev->touch = (tmp > 0); | ||
234 | dev->press = (tmp > 0 ? tmp : 0); | ||
235 | |||
236 | return 1; | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | |||
241 | /***************************************************************************** | ||
199 | * eGalax part | 242 | * eGalax part |
200 | */ | 243 | */ |
201 | 244 | ||
@@ -559,6 +602,21 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
559 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 602 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; |
560 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 603 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; |
561 | dev->touch = pkt[0] & 0x01; | 604 | dev->touch = pkt[0] & 0x01; |
605 | |||
606 | return 1; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | /***************************************************************************** | ||
611 | * JASTEC Part | ||
612 | */ | ||
613 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
614 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
615 | { | ||
616 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | ||
617 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | ||
618 | dev->touch = (pkt[0] & 0x40) >> 6; | ||
619 | |||
562 | return 1; | 620 | return 1; |
563 | } | 621 | } |
564 | #endif | 622 | #endif |
@@ -702,6 +760,29 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
702 | .read_data = gotop_read_data, | 760 | .read_data = gotop_read_data, |
703 | }, | 761 | }, |
704 | #endif | 762 | #endif |
763 | |||
764 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
765 | [DEVTYPE_JASTEC] = { | ||
766 | .min_xc = 0x0, | ||
767 | .max_xc = 0x0fff, | ||
768 | .min_yc = 0x0, | ||
769 | .max_yc = 0x0fff, | ||
770 | .rept_size = 4, | ||
771 | .read_data = jastec_read_data, | ||
772 | }, | ||
773 | #endif | ||
774 | |||
775 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
776 | [DEVTYPE_E2I] = { | ||
777 | .min_xc = 0x0, | ||
778 | .max_xc = 0x7fff, | ||
779 | .min_yc = 0x0, | ||
780 | .max_yc = 0x7fff, | ||
781 | .rept_size = 6, | ||
782 | .init = e2i_init, | ||
783 | .read_data = e2i_read_data, | ||
784 | }, | ||
785 | #endif | ||
705 | }; | 786 | }; |
706 | 787 | ||
707 | 788 | ||
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6071f5882572..6ccbdbbf33fe 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/clk.h> | ||
16 | #include <linux/input.h> | 17 | #include <linux/input.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | 19 | ||
@@ -47,8 +48,8 @@ enum ts_state { | |||
47 | struct w90p910_ts { | 48 | struct w90p910_ts { |
48 | struct input_dev *input; | 49 | struct input_dev *input; |
49 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | struct clk *clk; | ||
50 | int irq_num; | 52 | int irq_num; |
51 | void __iomem *clocken; | ||
52 | void __iomem *ts_reg; | 53 | void __iomem *ts_reg; |
53 | spinlock_t lock; | 54 | spinlock_t lock; |
54 | enum ts_state state; | 55 | enum ts_state state; |
@@ -166,8 +167,7 @@ static int w90p910_open(struct input_dev *dev) | |||
166 | unsigned long val; | 167 | unsigned long val; |
167 | 168 | ||
168 | /* enable the ADC clock */ | 169 | /* enable the ADC clock */ |
169 | val = __raw_readl(w90p910_ts->clocken); | 170 | clk_enable(w90p910_ts->clk); |
170 | __raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken); | ||
171 | 171 | ||
172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); | 172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); |
173 | msleep(1); | 173 | msleep(1); |
@@ -211,8 +211,7 @@ static void w90p910_close(struct input_dev *dev) | |||
211 | del_timer_sync(&w90p910_ts->timer); | 211 | del_timer_sync(&w90p910_ts->timer); |
212 | 212 | ||
213 | /* stop the ADC clock */ | 213 | /* stop the ADC clock */ |
214 | val = __raw_readl(w90p910_ts->clocken); | 214 | clk_disable(w90p910_ts->clk); |
215 | __raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken); | ||
216 | } | 215 | } |
217 | 216 | ||
218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) | 217 | static int __devinit w90x900ts_probe(struct platform_device *pdev) |
@@ -241,26 +240,24 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
241 | goto fail1; | 240 | goto fail1; |
242 | } | 241 | } |
243 | 242 | ||
244 | if (!request_mem_region(res->start, res->end - res->start + 1, | 243 | if (!request_mem_region(res->start, resource_size(res), |
245 | pdev->name)) { | 244 | pdev->name)) { |
246 | err = -EBUSY; | 245 | err = -EBUSY; |
247 | goto fail1; | 246 | goto fail1; |
248 | } | 247 | } |
249 | 248 | ||
250 | w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1); | 249 | w90p910_ts->ts_reg = ioremap(res->start, resource_size(res)); |
251 | if (!w90p910_ts->ts_reg) { | 250 | if (!w90p910_ts->ts_reg) { |
252 | err = -ENOMEM; | 251 | err = -ENOMEM; |
253 | goto fail2; | 252 | goto fail2; |
254 | } | 253 | } |
255 | 254 | ||
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 255 | w90p910_ts->clk = clk_get(&pdev->dev, NULL); |
257 | if (!res) { | 256 | if (IS_ERR(w90p910_ts->clk)) { |
258 | err = -ENXIO; | 257 | err = PTR_ERR(w90p910_ts->clk); |
259 | goto fail3; | 258 | goto fail3; |
260 | } | 259 | } |
261 | 260 | ||
262 | w90p910_ts->clocken = (void __iomem *)res->start; | ||
263 | |||
264 | input_dev->name = "W90P910 TouchScreen"; | 261 | input_dev->name = "W90P910 TouchScreen"; |
265 | input_dev->phys = "w90p910ts/event0"; | 262 | input_dev->phys = "w90p910ts/event0"; |
266 | input_dev->id.bustype = BUS_HOST; | 263 | input_dev->id.bustype = BUS_HOST; |
@@ -283,20 +280,21 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
283 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 280 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
284 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | 281 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { |
285 | err = -EBUSY; | 282 | err = -EBUSY; |
286 | goto fail3; | 283 | goto fail4; |
287 | } | 284 | } |
288 | 285 | ||
289 | err = input_register_device(w90p910_ts->input); | 286 | err = input_register_device(w90p910_ts->input); |
290 | if (err) | 287 | if (err) |
291 | goto fail4; | 288 | goto fail5; |
292 | 289 | ||
293 | platform_set_drvdata(pdev, w90p910_ts); | 290 | platform_set_drvdata(pdev, w90p910_ts); |
294 | 291 | ||
295 | return 0; | 292 | return 0; |
296 | 293 | ||
297 | fail4: free_irq(w90p910_ts->irq_num, w90p910_ts); | 294 | fail5: free_irq(w90p910_ts->irq_num, w90p910_ts); |
295 | fail4: clk_put(w90p910_ts->clk); | ||
298 | fail3: iounmap(w90p910_ts->ts_reg); | 296 | fail3: iounmap(w90p910_ts->ts_reg); |
299 | fail2: release_mem_region(res->start, res->end - res->start + 1); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
300 | fail1: input_free_device(input_dev); | 298 | fail1: input_free_device(input_dev); |
301 | kfree(w90p910_ts); | 299 | kfree(w90p910_ts); |
302 | return err; | 300 | return err; |
@@ -311,8 +309,10 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev) | |||
311 | del_timer_sync(&w90p910_ts->timer); | 309 | del_timer_sync(&w90p910_ts->timer); |
312 | iounmap(w90p910_ts->ts_reg); | 310 | iounmap(w90p910_ts->ts_reg); |
313 | 311 | ||
312 | clk_put(w90p910_ts->clk); | ||
313 | |||
314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
315 | release_mem_region(res->start, res->end - res->start + 1); | 315 | release_mem_region(res->start, resource_size(res)); |
316 | 316 | ||
317 | input_unregister_device(w90p910_ts->input); | 317 | input_unregister_device(w90p910_ts->input); |
318 | kfree(w90p910_ts); | 318 | kfree(w90p910_ts); |
@@ -326,7 +326,7 @@ static struct platform_driver w90x900ts_driver = { | |||
326 | .probe = w90x900ts_probe, | 326 | .probe = w90x900ts_probe, |
327 | .remove = __devexit_p(w90x900ts_remove), | 327 | .remove = __devexit_p(w90x900ts_remove), |
328 | .driver = { | 328 | .driver = { |
329 | .name = "w90x900-ts", | 329 | .name = "nuc900-ts", |
330 | .owner = THIS_MODULE, | 330 | .owner = THIS_MODULE, |
331 | }, | 331 | }, |
332 | }; | 332 | }; |
@@ -347,4 +347,4 @@ module_exit(w90x900ts_exit); | |||
347 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | 347 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); |
348 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); | 348 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); |
349 | MODULE_LICENSE("GPL"); | 349 | MODULE_LICENSE("GPL"); |
350 | MODULE_ALIAS("platform:w90p910-ts"); | 350 | MODULE_ALIAS("platform:nuc900-ts"); |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 2f33a0167644..56dc35c94bb1 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -25,18 +25,16 @@ MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>"); | |||
25 | MODULE_DESCRIPTION(DRIVER_DESC); | 25 | MODULE_DESCRIPTION(DRIVER_DESC); |
26 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
27 | 27 | ||
28 | /* | ||
29 | * Definitions & global arrays. | ||
30 | */ | ||
31 | |||
32 | #define W8001_MAX_LENGTH 11 | 28 | #define W8001_MAX_LENGTH 11 |
33 | #define W8001_PACKET_LEN 11 | 29 | #define W8001_LEAD_MASK 0x80 |
34 | #define W8001_LEAD_MASK 0x80 | 30 | #define W8001_LEAD_BYTE 0x80 |
35 | #define W8001_LEAD_BYTE 0x80 | 31 | #define W8001_TAB_MASK 0x40 |
36 | #define W8001_TAB_MASK 0x40 | 32 | #define W8001_TAB_BYTE 0x40 |
37 | #define W8001_TAB_BYTE 0x40 | ||
38 | 33 | ||
39 | #define W8001_QUERY_PACKET 0x20 | 34 | #define W8001_QUERY_PACKET 0x20 |
35 | |||
36 | #define W8001_CMD_START '1' | ||
37 | #define W8001_CMD_QUERY '*' | ||
40 | 38 | ||
41 | struct w8001_coord { | 39 | struct w8001_coord { |
42 | u8 rdy; | 40 | u8 rdy; |
@@ -57,18 +55,19 @@ struct w8001_coord { | |||
57 | struct w8001 { | 55 | struct w8001 { |
58 | struct input_dev *dev; | 56 | struct input_dev *dev; |
59 | struct serio *serio; | 57 | struct serio *serio; |
60 | struct mutex cmd_mutex; | ||
61 | struct completion cmd_done; | 58 | struct completion cmd_done; |
62 | int id; | 59 | int id; |
63 | int idx; | 60 | int idx; |
64 | unsigned char expected_packet; | 61 | unsigned char response_type; |
62 | unsigned char response[W8001_MAX_LENGTH]; | ||
65 | unsigned char data[W8001_MAX_LENGTH]; | 63 | unsigned char data[W8001_MAX_LENGTH]; |
66 | unsigned char response[W8001_PACKET_LEN]; | ||
67 | char phys[32]; | 64 | char phys[32]; |
68 | }; | 65 | }; |
69 | 66 | ||
70 | static int parse_data(u8 *data, struct w8001_coord *coord) | 67 | static void parse_data(u8 *data, struct w8001_coord *coord) |
71 | { | 68 | { |
69 | memset(coord, 0, sizeof(*coord)); | ||
70 | |||
72 | coord->rdy = data[0] & 0x20; | 71 | coord->rdy = data[0] & 0x20; |
73 | coord->tsw = data[0] & 0x01; | 72 | coord->tsw = data[0] & 0x01; |
74 | coord->f1 = data[0] & 0x02; | 73 | coord->f1 = data[0] & 0x02; |
@@ -87,15 +86,15 @@ static int parse_data(u8 *data, struct w8001_coord *coord) | |||
87 | 86 | ||
88 | coord->tilt_x = data[7] & 0x7F; | 87 | coord->tilt_x = data[7] & 0x7F; |
89 | coord->tilt_y = data[8] & 0x7F; | 88 | coord->tilt_y = data[8] & 0x7F; |
90 | |||
91 | return 0; | ||
92 | } | 89 | } |
93 | 90 | ||
94 | static void w8001_process_data(struct w8001 *w8001, unsigned char data) | 91 | static irqreturn_t w8001_interrupt(struct serio *serio, |
92 | unsigned char data, unsigned int flags) | ||
95 | { | 93 | { |
94 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
96 | struct input_dev *dev = w8001->dev; | 95 | struct input_dev *dev = w8001->dev; |
97 | u8 tmp; | ||
98 | struct w8001_coord coord; | 96 | struct w8001_coord coord; |
97 | unsigned char tmp; | ||
99 | 98 | ||
100 | w8001->data[w8001->idx] = data; | 99 | w8001->data[w8001->idx] = data; |
101 | switch (w8001->idx++) { | 100 | switch (w8001->idx++) { |
@@ -105,12 +104,13 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
105 | w8001->idx = 0; | 104 | w8001->idx = 0; |
106 | } | 105 | } |
107 | break; | 106 | break; |
107 | |||
108 | case 8: | 108 | case 8: |
109 | tmp = w8001->data[0] & W8001_TAB_MASK; | 109 | tmp = w8001->data[0] & W8001_TAB_MASK; |
110 | if (unlikely(tmp == W8001_TAB_BYTE)) | 110 | if (unlikely(tmp == W8001_TAB_BYTE)) |
111 | break; | 111 | break; |
112 | |||
112 | w8001->idx = 0; | 113 | w8001->idx = 0; |
113 | memset(&coord, 0, sizeof(coord)); | ||
114 | parse_data(w8001->data, &coord); | 114 | parse_data(w8001->data, &coord); |
115 | input_report_abs(dev, ABS_X, coord.x); | 115 | input_report_abs(dev, ABS_X, coord.x); |
116 | input_report_abs(dev, ABS_Y, coord.y); | 116 | input_report_abs(dev, ABS_Y, coord.y); |
@@ -118,86 +118,48 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
118 | input_report_key(dev, BTN_TOUCH, coord.tsw); | 118 | input_report_key(dev, BTN_TOUCH, coord.tsw); |
119 | input_sync(dev); | 119 | input_sync(dev); |
120 | break; | 120 | break; |
121 | |||
121 | case 10: | 122 | case 10: |
122 | w8001->idx = 0; | 123 | w8001->idx = 0; |
123 | memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN); | 124 | memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH); |
124 | w8001->expected_packet = W8001_QUERY_PACKET; | 125 | w8001->response_type = W8001_QUERY_PACKET; |
125 | complete(&w8001->cmd_done); | 126 | complete(&w8001->cmd_done); |
126 | break; | 127 | break; |
127 | } | 128 | } |
128 | } | ||
129 | |||
130 | |||
131 | static irqreturn_t w8001_interrupt(struct serio *serio, | ||
132 | unsigned char data, unsigned int flags) | ||
133 | { | ||
134 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
135 | |||
136 | w8001_process_data(w8001, data); | ||
137 | 129 | ||
138 | return IRQ_HANDLED; | 130 | return IRQ_HANDLED; |
139 | } | 131 | } |
140 | 132 | ||
141 | static int w8001_async_command(struct w8001 *w8001, unsigned char *packet, | 133 | static int w8001_command(struct w8001 *w8001, unsigned char command, |
142 | int len) | 134 | bool wait_response) |
143 | { | ||
144 | int rc = -1; | ||
145 | int i; | ||
146 | |||
147 | mutex_lock(&w8001->cmd_mutex); | ||
148 | |||
149 | for (i = 0; i < len; i++) { | ||
150 | if (serio_write(w8001->serio, packet[i])) | ||
151 | goto out; | ||
152 | } | ||
153 | rc = 0; | ||
154 | |||
155 | out: | ||
156 | mutex_unlock(&w8001->cmd_mutex); | ||
157 | return rc; | ||
158 | } | ||
159 | |||
160 | static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len) | ||
161 | { | 135 | { |
162 | int rc = -1; | 136 | int rc; |
163 | int i; | ||
164 | 137 | ||
165 | mutex_lock(&w8001->cmd_mutex); | 138 | w8001->response_type = 0; |
166 | |||
167 | serio_pause_rx(w8001->serio); | ||
168 | init_completion(&w8001->cmd_done); | 139 | init_completion(&w8001->cmd_done); |
169 | serio_continue_rx(w8001->serio); | ||
170 | |||
171 | for (i = 0; i < len; i++) { | ||
172 | if (serio_write(w8001->serio, packet[i])) | ||
173 | goto out; | ||
174 | } | ||
175 | 140 | ||
176 | wait_for_completion_timeout(&w8001->cmd_done, HZ); | 141 | rc = serio_write(w8001->serio, command); |
142 | if (rc == 0 && wait_response) { | ||
177 | 143 | ||
178 | if (w8001->expected_packet == W8001_QUERY_PACKET) { | 144 | wait_for_completion_timeout(&w8001->cmd_done, HZ); |
179 | /* We are back in reporting mode, the query was ACKed */ | 145 | if (w8001->response_type != W8001_QUERY_PACKET) |
180 | memcpy(packet, w8001->response, W8001_PACKET_LEN); | 146 | rc = -EIO; |
181 | rc = 0; | ||
182 | } | 147 | } |
183 | 148 | ||
184 | out: | ||
185 | mutex_unlock(&w8001->cmd_mutex); | ||
186 | return rc; | 149 | return rc; |
187 | } | 150 | } |
188 | 151 | ||
189 | static int w8001_setup(struct w8001 *w8001) | 152 | static int w8001_setup(struct w8001 *w8001) |
190 | { | 153 | { |
191 | struct w8001_coord coord; | ||
192 | struct input_dev *dev = w8001->dev; | 154 | struct input_dev *dev = w8001->dev; |
193 | unsigned char start[1] = { '1' }; | 155 | struct w8001_coord coord; |
194 | unsigned char query[11] = { '*' }; | 156 | int error; |
195 | 157 | ||
196 | if (w8001_command(w8001, query, 1)) | 158 | error = w8001_command(w8001, W8001_CMD_QUERY, true); |
197 | return -1; | 159 | if (error) |
160 | return error; | ||
198 | 161 | ||
199 | memset(&coord, 0, sizeof(coord)); | 162 | parse_data(w8001->response, &coord); |
200 | parse_data(query, &coord); | ||
201 | 163 | ||
202 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 164 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); |
203 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 165 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); |
@@ -205,10 +167,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
205 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | 167 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); |
206 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | 168 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); |
207 | 169 | ||
208 | if (w8001_async_command(w8001, start, 1)) | 170 | return w8001_command(w8001, W8001_CMD_START, false); |
209 | return -1; | ||
210 | |||
211 | return 0; | ||
212 | } | 171 | } |
213 | 172 | ||
214 | /* | 173 | /* |
@@ -249,7 +208,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
249 | w8001->serio = serio; | 208 | w8001->serio = serio; |
250 | w8001->id = serio->id.id; | 209 | w8001->id = serio->id.id; |
251 | w8001->dev = input_dev; | 210 | w8001->dev = input_dev; |
252 | mutex_init(&w8001->cmd_mutex); | ||
253 | init_completion(&w8001->cmd_done); | 211 | init_completion(&w8001->cmd_done); |
254 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 212 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
255 | 213 | ||
@@ -269,7 +227,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
269 | if (err) | 227 | if (err) |
270 | goto fail2; | 228 | goto fail2; |
271 | 229 | ||
272 | if (w8001_setup(w8001)) | 230 | err = w8001_setup(w8001); |
231 | if (err) | ||
273 | goto fail3; | 232 | goto fail3; |
274 | 233 | ||
275 | err = input_register_device(w8001->dev); | 234 | err = input_register_device(w8001->dev); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 2957d48e0045..252eb11fe9db 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -204,7 +204,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, | |||
204 | else | 204 | else |
205 | reg &= ~gpio; | 205 | reg &= ~gpio; |
206 | 206 | ||
207 | if (wm->id == WM9712_ID2) | 207 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); | 208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); |
209 | else | 209 | else |
210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); | 210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); |
@@ -307,7 +307,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
307 | WM97XX_GPIO_13); | 307 | WM97XX_GPIO_13); |
308 | } | 308 | } |
309 | 309 | ||
310 | if (wm->id == WM9712_ID2) | 310 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & | 311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & |
312 | ~WM97XX_GPIO_13) << 1); | 312 | ~WM97XX_GPIO_13) << 1); |
313 | else | 313 | else |
@@ -582,6 +582,8 @@ static int wm97xx_probe(struct device *dev) | |||
582 | 582 | ||
583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); | 583 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); |
584 | 584 | ||
585 | wm->variant = WM97xx_GENERIC; | ||
586 | |||
585 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); | 587 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); |
586 | 588 | ||
587 | switch (wm->id & 0xff) { | 589 | switch (wm->id & 0xff) { |