diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-05-22 02:36:56 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-05-22 02:36:56 -0400 |
commit | cf9b59e9d3e008591d1f54830f570982bb307a0d (patch) | |
tree | 113478ce8fd8c832ba726ffdf59b82cb46356476 /drivers/input | |
parent | 44504b2bebf8b5823c59484e73096a7d6574471d (diff) | |
parent | f4b87dee923342505e1ddba8d34ce9de33e75050 (diff) |
Merge remote branch 'origin' into secretlab/next-devicetree
Merging in current state of Linus' tree to deal with merge conflicts and
build failures in vio.c after merge.
Conflicts:
drivers/i2c/busses/i2c-cpm.c
drivers/i2c/busses/i2c-mpc.c
drivers/net/gianfar.c
Also fixed up one line in arch/powerpc/kernel/vio.c to use the
correct node pointer.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/input')
63 files changed, 4012 insertions, 3011 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf05a6..46239e47a26 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -59,11 +59,11 @@ static unsigned int get_time_pit(void) | |||
59 | unsigned long flags; | 59 | unsigned long flags; |
60 | unsigned int count; | 60 | unsigned int count; |
61 | 61 | ||
62 | spin_lock_irqsave(&i8253_lock, flags); | 62 | raw_spin_lock_irqsave(&i8253_lock, flags); |
63 | outb_p(0x00, 0x43); | 63 | outb_p(0x00, 0x43); |
64 | count = inb_p(0x40); | 64 | count = inb_p(0x40); |
65 | count |= inb_p(0x40) << 8; | 65 | count |= inb_p(0x40) << 8; |
66 | spin_unlock_irqrestore(&i8253_lock, flags); | 66 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
67 | 67 | ||
68 | return count; | 68 | return count; |
69 | } | 69 | } |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index c52bec4d053..423e0e6031a 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = { | |||
929 | .evbit = { BIT_MASK(EV_ABS) }, | 929 | .evbit = { BIT_MASK(EV_ABS) }, |
930 | .absbit = { BIT_MASK(ABS_THROTTLE) }, | 930 | .absbit = { BIT_MASK(ABS_THROTTLE) }, |
931 | }, | 931 | }, |
932 | { | ||
933 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
934 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
935 | .evbit = { BIT_MASK(EV_KEY) }, | ||
936 | .keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) }, | ||
937 | }, | ||
938 | { | ||
939 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
940 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
941 | .evbit = { BIT_MASK(EV_KEY) }, | ||
942 | .keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) }, | ||
943 | }, | ||
944 | { | ||
945 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
946 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
947 | .evbit = { BIT_MASK(EV_KEY) }, | ||
948 | .keybit = { [BIT_WORD(BTN_TRIGGER_HAPPY)] = BIT_MASK(BTN_TRIGGER_HAPPY) }, | ||
949 | }, | ||
932 | { } /* Terminating entry */ | 950 | { } /* Terminating entry */ |
933 | }; | 951 | }; |
934 | 952 | ||
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529c06a..4afe0a3b488 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -146,11 +146,11 @@ static unsigned int get_time_pit(void) | |||
146 | unsigned long flags; | 146 | unsigned long flags; |
147 | unsigned int count; | 147 | unsigned int count; |
148 | 148 | ||
149 | spin_lock_irqsave(&i8253_lock, flags); | 149 | raw_spin_lock_irqsave(&i8253_lock, flags); |
150 | outb_p(0x00, 0x43); | 150 | outb_p(0x00, 0x43); |
151 | count = inb_p(0x40); | 151 | count = inb_p(0x40); |
152 | count |= inb_p(0x40) << 8; | 152 | count |= inb_p(0x40) << 8; |
153 | spin_unlock_irqrestore(&i8253_lock, flags); | 153 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
154 | 154 | ||
155 | return count; | 155 | return count; |
156 | } | 156 | } |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b1edd778639..405febd94f2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -54,6 +54,9 @@ static signed short btn_avb_wheel[] = | |||
54 | static signed short abs_joystick[] = | 54 | static signed short abs_joystick[] = |
55 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; | 55 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; |
56 | 56 | ||
57 | static signed short abs_joystick_rudder[] = | ||
58 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 }; | ||
59 | |||
57 | static signed short abs_avb_pegasus[] = | 60 | static signed short abs_avb_pegasus[] = |
58 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, | 61 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, |
59 | ABS_HAT1X, ABS_HAT1Y, -1 }; | 62 | ABS_HAT1X, ABS_HAT1Y, -1 }; |
@@ -76,8 +79,9 @@ static struct iforce_device iforce_device[] = { | |||
76 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
77 | { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, | 80 | { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, |
78 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 81 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
82 | { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, | ||
79 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 83 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
80 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | 84 | { 0x06f8, 0xa302, "Guillemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? |
81 | { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, | 85 | { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, |
82 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 86 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
83 | }; | 87 | }; |
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b41303d3ec5..6c96631ae5d 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
@@ -212,6 +212,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
212 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 212 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
213 | { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ | 213 | { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ |
214 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 214 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
215 | { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */ | ||
215 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 216 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
216 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | 217 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ |
217 | { } /* Terminating entry */ | 218 | { } /* Terminating entry */ |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 9b3353b404d..c1087ce4cef 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -533,8 +533,8 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
533 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) | 533 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) |
534 | return 0; | 534 | return 0; |
535 | 535 | ||
536 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, | 536 | xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, |
537 | GFP_KERNEL, &xpad->odata_dma); | 537 | GFP_KERNEL, &xpad->odata_dma); |
538 | if (!xpad->odata) | 538 | if (!xpad->odata) |
539 | goto fail1; | 539 | goto fail1; |
540 | 540 | ||
@@ -554,7 +554,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
554 | 554 | ||
555 | return 0; | 555 | return 0; |
556 | 556 | ||
557 | fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); | 557 | fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); |
558 | fail1: return error; | 558 | fail1: return error; |
559 | } | 559 | } |
560 | 560 | ||
@@ -568,7 +568,7 @@ static void xpad_deinit_output(struct usb_xpad *xpad) | |||
568 | { | 568 | { |
569 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { | 569 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { |
570 | usb_free_urb(xpad->irq_out); | 570 | usb_free_urb(xpad->irq_out); |
571 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, | 571 | usb_free_coherent(xpad->udev, XPAD_PKT_LEN, |
572 | xpad->odata, xpad->odata_dma); | 572 | xpad->odata, xpad->odata_dma); |
573 | } | 573 | } |
574 | } | 574 | } |
@@ -788,8 +788,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
788 | if (!xpad || !input_dev) | 788 | if (!xpad || !input_dev) |
789 | goto fail1; | 789 | goto fail1; |
790 | 790 | ||
791 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | 791 | xpad->idata = usb_alloc_coherent(udev, XPAD_PKT_LEN, |
792 | GFP_KERNEL, &xpad->idata_dma); | 792 | GFP_KERNEL, &xpad->idata_dma); |
793 | if (!xpad->idata) | 793 | if (!xpad->idata) |
794 | goto fail1; | 794 | goto fail1; |
795 | 795 | ||
@@ -942,7 +942,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
942 | fail5: usb_kill_urb(xpad->irq_in); | 942 | fail5: usb_kill_urb(xpad->irq_in); |
943 | fail4: usb_free_urb(xpad->irq_in); | 943 | fail4: usb_free_urb(xpad->irq_in); |
944 | fail3: xpad_deinit_output(xpad); | 944 | fail3: xpad_deinit_output(xpad); |
945 | fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); | 945 | fail2: usb_free_coherent(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); |
946 | fail1: input_free_device(input_dev); | 946 | fail1: input_free_device(input_dev); |
947 | kfree(xpad); | 947 | kfree(xpad); |
948 | return error; | 948 | return error; |
@@ -964,7 +964,7 @@ static void xpad_disconnect(struct usb_interface *intf) | |||
964 | usb_kill_urb(xpad->irq_in); | 964 | usb_kill_urb(xpad->irq_in); |
965 | } | 965 | } |
966 | usb_free_urb(xpad->irq_in); | 966 | usb_free_urb(xpad->irq_in); |
967 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, | 967 | usb_free_coherent(xpad->udev, XPAD_PKT_LEN, |
968 | xpad->idata, xpad->idata_dma); | 968 | xpad->idata, xpad->idata_dma); |
969 | kfree(xpad); | 969 | kfree(xpad); |
970 | } | 970 | } |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c102355f5..d8fa5d724c5 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -73,7 +73,7 @@ config KEYBOARD_ATKBD | |||
73 | default y | 73 | default y |
74 | select SERIO | 74 | select SERIO |
75 | select SERIO_LIBPS2 | 75 | select SERIO_LIBPS2 |
76 | select SERIO_I8042 if X86 | 76 | select SERIO_I8042 if X86 && !X86_MRST |
77 | select SERIO_GSCPS2 if GSC | 77 | select SERIO_GSCPS2 if GSC |
78 | help | 78 | help |
79 | Say Y here if you want to use a standard AT or PS/2 keyboard. Usually | 79 | Say Y here if you want to use a standard AT or PS/2 keyboard. Usually |
@@ -143,19 +143,6 @@ config KEYBOARD_BFIN | |||
143 | To compile this driver as a module, choose M here: the | 143 | To compile this driver as a module, choose M here: the |
144 | module will be called bf54x-keys. | 144 | module will be called bf54x-keys. |
145 | 145 | ||
146 | config KEYBOARD_CORGI | ||
147 | tristate "Corgi keyboard (deprecated)" | ||
148 | depends on PXA_SHARPSL | ||
149 | help | ||
150 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | ||
151 | series of PDAs. | ||
152 | |||
153 | This driver is now deprecated, use generic GPIO based matrix | ||
154 | keyboard driver instead. | ||
155 | |||
156 | To compile this driver as a module, choose M here: the | ||
157 | module will be called corgikbd. | ||
158 | |||
159 | config KEYBOARD_LKKBD | 146 | config KEYBOARD_LKKBD |
160 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | 147 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
161 | select SERIO | 148 | select SERIO |
@@ -192,6 +179,22 @@ config KEYBOARD_GPIO | |||
192 | To compile this driver as a module, choose M here: the | 179 | To compile this driver as a module, choose M here: the |
193 | module will be called gpio_keys. | 180 | module will be called gpio_keys. |
194 | 181 | ||
182 | config KEYBOARD_TCA6416 | ||
183 | tristate "TCA6416 Keypad Support" | ||
184 | depends on I2C | ||
185 | help | ||
186 | This driver implements basic keypad functionality | ||
187 | for keys connected through TCA6416 IO expander | ||
188 | |||
189 | Say Y here if your device has keys connected to | ||
190 | TCA6416 IO expander. Your board-specific setup logic | ||
191 | must also provide pin-mask details(of which TCA6416 pins | ||
192 | are used for keypad). | ||
193 | |||
194 | If enabled the complete TCA6416 device will be managed through | ||
195 | this driver. | ||
196 | |||
197 | |||
195 | config KEYBOARD_MATRIX | 198 | config KEYBOARD_MATRIX |
196 | tristate "GPIO driven matrix keypad support" | 199 | tristate "GPIO driven matrix keypad support" |
197 | depends on GENERIC_GPIO | 200 | depends on GENERIC_GPIO |
@@ -339,19 +342,6 @@ config KEYBOARD_PXA930_ROTARY | |||
339 | To compile this driver as a module, choose M here: the | 342 | To compile this driver as a module, choose M here: the |
340 | module will be called pxa930_rotary. | 343 | module will be called pxa930_rotary. |
341 | 344 | ||
342 | config KEYBOARD_SPITZ | ||
343 | tristate "Spitz keyboard (deprecated)" | ||
344 | depends on PXA_SHARPSL | ||
345 | help | ||
346 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | ||
347 | SL-C3000 and Sl-C3100 series of PDAs. | ||
348 | |||
349 | This driver is now deprecated, use generic GPIO based matrix | ||
350 | keyboard driver instead. | ||
351 | |||
352 | To compile this driver as a module, choose M here: the | ||
353 | module will be called spitzkbd. | ||
354 | |||
355 | config KEYBOARD_STOWAWAY | 345 | config KEYBOARD_STOWAWAY |
356 | tristate "Stowaway keyboard" | 346 | tristate "Stowaway keyboard" |
357 | select SERIO | 347 | select SERIO |
@@ -414,28 +404,6 @@ config KEYBOARD_TWL4030 | |||
414 | To compile this driver as a module, choose M here: the | 404 | To compile this driver as a module, choose M here: the |
415 | module will be called twl4030_keypad. | 405 | module will be called twl4030_keypad. |
416 | 406 | ||
417 | config KEYBOARD_TOSA | ||
418 | tristate "Tosa keyboard (deprecated)" | ||
419 | depends on MACH_TOSA | ||
420 | help | ||
421 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
422 | |||
423 | This driver is now deprecated, use generic GPIO based matrix | ||
424 | keyboard driver instead. | ||
425 | |||
426 | To compile this driver as a module, choose M here: the | ||
427 | module will be called tosakbd. | ||
428 | |||
429 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
430 | bool "Tosa keyboard: use extended keycodes" | ||
431 | depends on KEYBOARD_TOSA | ||
432 | help | ||
433 | Say Y here to enable the tosa keyboard driver to generate extended | ||
434 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
435 | by either console keyboard driver or by Kdrive keybd driver. | ||
436 | |||
437 | Say Y only if you know, what you are doing! | ||
438 | |||
439 | config KEYBOARD_XTKBD | 407 | config KEYBOARD_XTKBD |
440 | tristate "XT keyboard" | 408 | tristate "XT keyboard" |
441 | select SERIO | 409 | select SERIO |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5ed5f..4596d0c6f92 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -11,10 +11,10 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
14 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | ||
15 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 14 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
16 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 15 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
17 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 16 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
17 | obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o | ||
18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
20 | obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o | 20 | obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o |
@@ -33,10 +33,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | |||
33 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 33 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
34 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 34 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
35 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 35 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
36 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | ||
37 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 36 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
38 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 37 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
39 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 38 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
41 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 39 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
42 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | 40 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a8e6b..00000000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null | |||
@@ -1,414 +0,0 @@ | |||
1 | /* | ||
2 | * Keyboard driver for Sharp Corgi models (SL-C7xx) | ||
3 | * | ||
4 | * Copyright (c) 2004-2005 Richard Purdie | ||
5 | * | ||
6 | * Based on xtkbd.c/locomkbd.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <mach/corgi.h> | ||
24 | #include <mach/pxa2xx-gpio.h> | ||
25 | #include <asm/hardware/scoop.h> | ||
26 | |||
27 | #define KB_ROWS 8 | ||
28 | #define KB_COLS 12 | ||
29 | #define KB_ROWMASK(r) (1 << (r)) | ||
30 | #define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) | ||
31 | /* zero code, 124 scancodes */ | ||
32 | #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) | ||
33 | |||
34 | #define SCAN_INTERVAL (50) /* ms */ | ||
35 | #define HINGE_SCAN_INTERVAL (250) /* ms */ | ||
36 | |||
37 | #define CORGI_KEY_CALENDER KEY_F1 | ||
38 | #define CORGI_KEY_ADDRESS KEY_F2 | ||
39 | #define CORGI_KEY_FN KEY_F3 | ||
40 | #define CORGI_KEY_CANCEL KEY_F4 | ||
41 | #define CORGI_KEY_OFF KEY_SUSPEND | ||
42 | #define CORGI_KEY_EXOK KEY_F5 | ||
43 | #define CORGI_KEY_EXCANCEL KEY_F6 | ||
44 | #define CORGI_KEY_EXJOGDOWN KEY_F7 | ||
45 | #define CORGI_KEY_EXJOGUP KEY_F8 | ||
46 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | ||
47 | #define CORGI_KEY_JAP2 KEY_LEFTALT | ||
48 | #define CORGI_KEY_MAIL KEY_F10 | ||
49 | #define CORGI_KEY_OK KEY_F11 | ||
50 | #define CORGI_KEY_MENU KEY_F12 | ||
51 | |||
52 | static unsigned char corgikbd_keycode[NR_SCANCODES] = { | ||
53 | 0, /* 0 */ | ||
54 | 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ | ||
55 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ | ||
56 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
57 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
58 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | ||
59 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | ||
60 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | ||
61 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | ||
62 | }; | ||
63 | |||
64 | |||
65 | struct corgikbd { | ||
66 | unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; | ||
67 | struct input_dev *input; | ||
68 | |||
69 | spinlock_t lock; | ||
70 | struct timer_list timer; | ||
71 | struct timer_list htimer; | ||
72 | |||
73 | unsigned int suspended; | ||
74 | unsigned long suspend_jiffies; | ||
75 | }; | ||
76 | |||
77 | #define KB_DISCHARGE_DELAY 10 | ||
78 | #define KB_ACTIVATE_DELAY 10 | ||
79 | |||
80 | /* Helper functions for reading the keyboard matrix | ||
81 | * Note: We should really be using the generic gpio functions to alter | ||
82 | * GPDR but it requires a function call per GPIO bit which is | ||
83 | * excessive when we need to access 12 bits at once, multiple times. | ||
84 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
85 | * or similar. | ||
86 | */ | ||
87 | static inline void corgikbd_discharge_all(void) | ||
88 | { | ||
89 | /* STROBE All HiZ */ | ||
90 | GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
91 | GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; | ||
92 | } | ||
93 | |||
94 | static inline void corgikbd_activate_all(void) | ||
95 | { | ||
96 | /* STROBE ALL -> High */ | ||
97 | GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
98 | GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; | ||
99 | |||
100 | udelay(KB_DISCHARGE_DELAY); | ||
101 | |||
102 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
103 | GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; | ||
104 | GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; | ||
105 | } | ||
106 | |||
107 | static inline void corgikbd_activate_col(int col) | ||
108 | { | ||
109 | /* STROBE col -> High, not col -> HiZ */ | ||
110 | GPSR2 = CORGI_GPIO_STROBE_BIT(col); | ||
111 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
112 | } | ||
113 | |||
114 | static inline void corgikbd_reset_col(int col) | ||
115 | { | ||
116 | /* STROBE col -> Low */ | ||
117 | GPCR2 = CORGI_GPIO_STROBE_BIT(col); | ||
118 | /* STROBE col -> out, not col -> HiZ */ | ||
119 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
120 | } | ||
121 | |||
122 | #define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) | ||
123 | |||
124 | /* | ||
125 | * The corgi keyboard only generates interrupts when a key is pressed. | ||
126 | * When a key is pressed, we enable a timer which then scans the | ||
127 | * keyboard to detect when the key is released. | ||
128 | */ | ||
129 | |||
130 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
131 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) | ||
132 | { | ||
133 | unsigned int row, col, rowd; | ||
134 | unsigned long flags; | ||
135 | unsigned int num_pressed; | ||
136 | |||
137 | if (corgikbd_data->suspended) | ||
138 | return; | ||
139 | |||
140 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
141 | |||
142 | num_pressed = 0; | ||
143 | for (col = 0; col < KB_COLS; col++) { | ||
144 | /* | ||
145 | * Discharge the output driver capacitatance | ||
146 | * in the keyboard matrix. (Yes it is significant..) | ||
147 | */ | ||
148 | |||
149 | corgikbd_discharge_all(); | ||
150 | udelay(KB_DISCHARGE_DELAY); | ||
151 | |||
152 | corgikbd_activate_col(col); | ||
153 | udelay(KB_ACTIVATE_DELAY); | ||
154 | |||
155 | rowd = GET_ROWS_STATUS(col); | ||
156 | for (row = 0; row < KB_ROWS; row++) { | ||
157 | unsigned int scancode, pressed; | ||
158 | |||
159 | scancode = SCANCODE(row, col); | ||
160 | pressed = rowd & KB_ROWMASK(row); | ||
161 | |||
162 | input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); | ||
163 | |||
164 | if (pressed) | ||
165 | num_pressed++; | ||
166 | |||
167 | if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | ||
168 | && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { | ||
169 | input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | ||
170 | corgikbd_data->suspend_jiffies=jiffies; | ||
171 | } | ||
172 | } | ||
173 | corgikbd_reset_col(col); | ||
174 | } | ||
175 | |||
176 | corgikbd_activate_all(); | ||
177 | |||
178 | input_sync(corgikbd_data->input); | ||
179 | |||
180 | /* if any keys are pressed, enable the timer */ | ||
181 | if (num_pressed) | ||
182 | mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
183 | |||
184 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * corgi keyboard interrupt handler. | ||
189 | */ | ||
190 | static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) | ||
191 | { | ||
192 | struct corgikbd *corgikbd_data = dev_id; | ||
193 | |||
194 | if (!timer_pending(&corgikbd_data->timer)) { | ||
195 | /** wait chattering delay **/ | ||
196 | udelay(20); | ||
197 | corgikbd_scankeyboard(corgikbd_data); | ||
198 | } | ||
199 | |||
200 | return IRQ_HANDLED; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * corgi timer checking for released keys | ||
205 | */ | ||
206 | static void corgikbd_timer_callback(unsigned long data) | ||
207 | { | ||
208 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
209 | corgikbd_scankeyboard(corgikbd_data); | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * The hinge switches generate no interrupt so they need to be | ||
214 | * monitored by a timer. | ||
215 | * | ||
216 | * We debounce the switches and pass them to the input system. | ||
217 | * | ||
218 | * gprr == 0x00 - Keyboard with Landscape Screen | ||
219 | * 0x08 - No Keyboard with Portrait Screen | ||
220 | * 0x0c - Keyboard and Screen Closed | ||
221 | */ | ||
222 | |||
223 | #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) | ||
224 | #define HINGE_STABLE_COUNT 2 | ||
225 | static int sharpsl_hinge_state; | ||
226 | static int hinge_count; | ||
227 | |||
228 | static void corgikbd_hinge_timer(unsigned long data) | ||
229 | { | ||
230 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
231 | unsigned long gprr; | ||
232 | unsigned long flags; | ||
233 | |||
234 | gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); | ||
235 | gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); | ||
236 | if (gprr != sharpsl_hinge_state) { | ||
237 | hinge_count = 0; | ||
238 | sharpsl_hinge_state = gprr; | ||
239 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
240 | hinge_count++; | ||
241 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
242 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
243 | |||
244 | input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); | ||
245 | input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); | ||
246 | input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); | ||
247 | input_sync(corgikbd_data->input); | ||
248 | |||
249 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
250 | } | ||
251 | } | ||
252 | mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
253 | } | ||
254 | |||
255 | #ifdef CONFIG_PM | ||
256 | static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) | ||
257 | { | ||
258 | int i; | ||
259 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
260 | |||
261 | corgikbd->suspended = 1; | ||
262 | /* strobe 0 is the power key so this can't be made an input for | ||
263 | powersaving therefore i = 1 */ | ||
264 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
265 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int corgikbd_resume(struct platform_device *dev) | ||
271 | { | ||
272 | int i; | ||
273 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
274 | |||
275 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
276 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
277 | |||
278 | /* Upon resume, ignore the suspend key for a short while */ | ||
279 | corgikbd->suspend_jiffies=jiffies; | ||
280 | corgikbd->suspended = 0; | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | #else | ||
285 | #define corgikbd_suspend NULL | ||
286 | #define corgikbd_resume NULL | ||
287 | #endif | ||
288 | |||
289 | static int __devinit corgikbd_probe(struct platform_device *pdev) | ||
290 | { | ||
291 | struct corgikbd *corgikbd; | ||
292 | struct input_dev *input_dev; | ||
293 | int i, err = -ENOMEM; | ||
294 | |||
295 | corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); | ||
296 | input_dev = input_allocate_device(); | ||
297 | if (!corgikbd || !input_dev) | ||
298 | goto fail; | ||
299 | |||
300 | platform_set_drvdata(pdev, corgikbd); | ||
301 | |||
302 | corgikbd->input = input_dev; | ||
303 | spin_lock_init(&corgikbd->lock); | ||
304 | |||
305 | /* Init Keyboard rescan timer */ | ||
306 | init_timer(&corgikbd->timer); | ||
307 | corgikbd->timer.function = corgikbd_timer_callback; | ||
308 | corgikbd->timer.data = (unsigned long) corgikbd; | ||
309 | |||
310 | /* Init Hinge Timer */ | ||
311 | init_timer(&corgikbd->htimer); | ||
312 | corgikbd->htimer.function = corgikbd_hinge_timer; | ||
313 | corgikbd->htimer.data = (unsigned long) corgikbd; | ||
314 | |||
315 | corgikbd->suspend_jiffies=jiffies; | ||
316 | |||
317 | memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); | ||
318 | |||
319 | input_dev->name = "Corgi Keyboard"; | ||
320 | input_dev->phys = "corgikbd/input0"; | ||
321 | input_dev->id.bustype = BUS_HOST; | ||
322 | input_dev->id.vendor = 0x0001; | ||
323 | input_dev->id.product = 0x0001; | ||
324 | input_dev->id.version = 0x0100; | ||
325 | input_dev->dev.parent = &pdev->dev; | ||
326 | |||
327 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
328 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
329 | input_dev->keycode = corgikbd->keycode; | ||
330 | input_dev->keycodesize = sizeof(unsigned char); | ||
331 | input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); | ||
332 | |||
333 | for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) | ||
334 | set_bit(corgikbd->keycode[i], input_dev->keybit); | ||
335 | clear_bit(0, input_dev->keybit); | ||
336 | set_bit(SW_LID, input_dev->swbit); | ||
337 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
338 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
339 | |||
340 | err = input_register_device(corgikbd->input); | ||
341 | if (err) | ||
342 | goto fail; | ||
343 | |||
344 | mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
345 | |||
346 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
347 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { | ||
348 | pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); | ||
349 | if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, | ||
350 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
351 | "corgikbd", corgikbd)) | ||
352 | printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); | ||
353 | } | ||
354 | |||
355 | /* Set Strobe lines as outputs - set high */ | ||
356 | for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) | ||
357 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
358 | |||
359 | /* Setup the headphone jack as an input */ | ||
360 | pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); | ||
361 | |||
362 | return 0; | ||
363 | |||
364 | fail: input_free_device(input_dev); | ||
365 | kfree(corgikbd); | ||
366 | return err; | ||
367 | } | ||
368 | |||
369 | static int __devexit corgikbd_remove(struct platform_device *pdev) | ||
370 | { | ||
371 | int i; | ||
372 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); | ||
373 | |||
374 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) | ||
375 | free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); | ||
376 | |||
377 | del_timer_sync(&corgikbd->htimer); | ||
378 | del_timer_sync(&corgikbd->timer); | ||
379 | |||
380 | input_unregister_device(corgikbd->input); | ||
381 | |||
382 | kfree(corgikbd); | ||
383 | |||
384 | return 0; | ||
385 | } | ||
386 | |||
387 | static struct platform_driver corgikbd_driver = { | ||
388 | .probe = corgikbd_probe, | ||
389 | .remove = __devexit_p(corgikbd_remove), | ||
390 | .suspend = corgikbd_suspend, | ||
391 | .resume = corgikbd_resume, | ||
392 | .driver = { | ||
393 | .name = "corgi-keyboard", | ||
394 | .owner = THIS_MODULE, | ||
395 | }, | ||
396 | }; | ||
397 | |||
398 | static int __init corgikbd_init(void) | ||
399 | { | ||
400 | return platform_driver_register(&corgikbd_driver); | ||
401 | } | ||
402 | |||
403 | static void __exit corgikbd_exit(void) | ||
404 | { | ||
405 | platform_driver_unregister(&corgikbd_driver); | ||
406 | } | ||
407 | |||
408 | module_init(corgikbd_init); | ||
409 | module_exit(corgikbd_exit); | ||
410 | |||
411 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
412 | MODULE_DESCRIPTION("Corgi Keyboard Driver"); | ||
413 | MODULE_LICENSE("GPL v2"); | ||
414 | MODULE_ALIAS("platform:corgi-keyboard"); | ||
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 60ac4684f87..bc696931fed 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -670,8 +670,6 @@ static int __devinit lm8323_probe(struct i2c_client *client, | |||
670 | goto fail1; | 670 | goto fail1; |
671 | } | 671 | } |
672 | 672 | ||
673 | i2c_set_clientdata(client, lm); | ||
674 | |||
675 | lm->client = client; | 673 | lm->client = client; |
676 | lm->idev = idev; | 674 | lm->idev = idev; |
677 | mutex_init(&lm->lock); | 675 | mutex_init(&lm->lock); |
@@ -753,6 +751,8 @@ static int __devinit lm8323_probe(struct i2c_client *client, | |||
753 | goto fail4; | 751 | goto fail4; |
754 | } | 752 | } |
755 | 753 | ||
754 | i2c_set_clientdata(client, lm); | ||
755 | |||
756 | device_init_wakeup(&client->dev, 1); | 756 | device_init_wakeup(&client->dev, 1); |
757 | enable_irq_wake(client->irq); | 757 | enable_irq_wake(client->irq); |
758 | 758 | ||
@@ -778,6 +778,8 @@ static int __devexit lm8323_remove(struct i2c_client *client) | |||
778 | struct lm8323_chip *lm = i2c_get_clientdata(client); | 778 | struct lm8323_chip *lm = i2c_get_clientdata(client); |
779 | int i; | 779 | int i; |
780 | 780 | ||
781 | i2c_set_clientdata(client, NULL); | ||
782 | |||
781 | disable_irq_wake(client->irq); | 783 | disable_irq_wake(client->irq); |
782 | free_irq(client->irq, lm); | 784 | free_irq(client->irq, lm); |
783 | cancel_work_sync(&lm->work); | 785 | cancel_work_sync(&lm->work); |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 13967422658..00000000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null | |||
@@ -1,496 +0,0 @@ | |||
1 | /* | ||
2 | * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * Based on corgikbd.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <mach/spitz.h> | ||
24 | #include <mach/pxa2xx-gpio.h> | ||
25 | |||
26 | #define KB_ROWS 7 | ||
27 | #define KB_COLS 11 | ||
28 | #define KB_ROWMASK(r) (1 << (r)) | ||
29 | #define SCANCODE(r,c) (((r)<<4) + (c) + 1) | ||
30 | #define NR_SCANCODES ((KB_ROWS<<4) + 1) | ||
31 | |||
32 | #define SCAN_INTERVAL (50) /* ms */ | ||
33 | #define HINGE_SCAN_INTERVAL (150) /* ms */ | ||
34 | |||
35 | #define SPITZ_KEY_CALENDER KEY_F1 | ||
36 | #define SPITZ_KEY_ADDRESS KEY_F2 | ||
37 | #define SPITZ_KEY_FN KEY_F3 | ||
38 | #define SPITZ_KEY_CANCEL KEY_F4 | ||
39 | #define SPITZ_KEY_EXOK KEY_F5 | ||
40 | #define SPITZ_KEY_EXCANCEL KEY_F6 | ||
41 | #define SPITZ_KEY_EXJOGDOWN KEY_F7 | ||
42 | #define SPITZ_KEY_EXJOGUP KEY_F8 | ||
43 | #define SPITZ_KEY_JAP1 KEY_LEFTALT | ||
44 | #define SPITZ_KEY_JAP2 KEY_RIGHTCTRL | ||
45 | #define SPITZ_KEY_SYNC KEY_F9 | ||
46 | #define SPITZ_KEY_MAIL KEY_F10 | ||
47 | #define SPITZ_KEY_OK KEY_F11 | ||
48 | #define SPITZ_KEY_MENU KEY_F12 | ||
49 | |||
50 | static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | ||
51 | 0, /* 0 */ | ||
52 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | ||
53 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | ||
54 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
55 | SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
56 | SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | ||
57 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | ||
58 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | ||
59 | }; | ||
60 | |||
61 | static int spitz_strobes[] = { | ||
62 | SPITZ_GPIO_KEY_STROBE0, | ||
63 | SPITZ_GPIO_KEY_STROBE1, | ||
64 | SPITZ_GPIO_KEY_STROBE2, | ||
65 | SPITZ_GPIO_KEY_STROBE3, | ||
66 | SPITZ_GPIO_KEY_STROBE4, | ||
67 | SPITZ_GPIO_KEY_STROBE5, | ||
68 | SPITZ_GPIO_KEY_STROBE6, | ||
69 | SPITZ_GPIO_KEY_STROBE7, | ||
70 | SPITZ_GPIO_KEY_STROBE8, | ||
71 | SPITZ_GPIO_KEY_STROBE9, | ||
72 | SPITZ_GPIO_KEY_STROBE10, | ||
73 | }; | ||
74 | |||
75 | static int spitz_senses[] = { | ||
76 | SPITZ_GPIO_KEY_SENSE0, | ||
77 | SPITZ_GPIO_KEY_SENSE1, | ||
78 | SPITZ_GPIO_KEY_SENSE2, | ||
79 | SPITZ_GPIO_KEY_SENSE3, | ||
80 | SPITZ_GPIO_KEY_SENSE4, | ||
81 | SPITZ_GPIO_KEY_SENSE5, | ||
82 | SPITZ_GPIO_KEY_SENSE6, | ||
83 | }; | ||
84 | |||
85 | struct spitzkbd { | ||
86 | unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; | ||
87 | struct input_dev *input; | ||
88 | char phys[32]; | ||
89 | |||
90 | spinlock_t lock; | ||
91 | struct timer_list timer; | ||
92 | struct timer_list htimer; | ||
93 | |||
94 | unsigned int suspended; | ||
95 | unsigned long suspend_jiffies; | ||
96 | }; | ||
97 | |||
98 | #define KB_DISCHARGE_DELAY 10 | ||
99 | #define KB_ACTIVATE_DELAY 10 | ||
100 | |||
101 | /* Helper functions for reading the keyboard matrix | ||
102 | * Note: We should really be using the generic gpio functions to alter | ||
103 | * GPDR but it requires a function call per GPIO bit which is | ||
104 | * excessive when we need to access 11 bits at once, multiple times. | ||
105 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
106 | * or similar. | ||
107 | */ | ||
108 | static inline void spitzkbd_discharge_all(void) | ||
109 | { | ||
110 | /* STROBE All HiZ */ | ||
111 | GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
112 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
113 | GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
114 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
115 | GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
116 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
117 | GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
118 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
119 | } | ||
120 | |||
121 | static inline void spitzkbd_activate_all(void) | ||
122 | { | ||
123 | /* STROBE ALL -> High */ | ||
124 | GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
125 | GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; | ||
126 | GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
127 | GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; | ||
128 | GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
129 | GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; | ||
130 | GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
131 | GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; | ||
132 | |||
133 | udelay(KB_DISCHARGE_DELAY); | ||
134 | |||
135 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
136 | GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; | ||
137 | GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; | ||
138 | GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; | ||
139 | GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; | ||
140 | } | ||
141 | |||
142 | static inline void spitzkbd_activate_col(int col) | ||
143 | { | ||
144 | int gpio = spitz_strobes[col]; | ||
145 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
146 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
147 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
148 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
149 | GPSR(gpio) = GPIO_bit(gpio); | ||
150 | GPDR(gpio) |= GPIO_bit(gpio); | ||
151 | } | ||
152 | |||
153 | static inline void spitzkbd_reset_col(int col) | ||
154 | { | ||
155 | int gpio = spitz_strobes[col]; | ||
156 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
157 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
158 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
159 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
160 | GPCR(gpio) = GPIO_bit(gpio); | ||
161 | GPDR(gpio) |= GPIO_bit(gpio); | ||
162 | } | ||
163 | |||
164 | static inline int spitzkbd_get_row_status(int col) | ||
165 | { | ||
166 | return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) | ||
167 | | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) | ||
168 | | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * The spitz keyboard only generates interrupts when a key is pressed. | ||
173 | * When a key is pressed, we enable a timer which then scans the | ||
174 | * keyboard to detect when the key is released. | ||
175 | */ | ||
176 | |||
177 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
178 | static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) | ||
179 | { | ||
180 | unsigned int row, col, rowd; | ||
181 | unsigned long flags; | ||
182 | unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); | ||
183 | |||
184 | if (spitzkbd_data->suspended) | ||
185 | return; | ||
186 | |||
187 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
188 | |||
189 | num_pressed = 0; | ||
190 | for (col = 0; col < KB_COLS; col++) { | ||
191 | /* | ||
192 | * Discharge the output driver capacitatance | ||
193 | * in the keyboard matrix. (Yes it is significant..) | ||
194 | */ | ||
195 | |||
196 | spitzkbd_discharge_all(); | ||
197 | udelay(KB_DISCHARGE_DELAY); | ||
198 | |||
199 | spitzkbd_activate_col(col); | ||
200 | udelay(KB_ACTIVATE_DELAY); | ||
201 | |||
202 | rowd = spitzkbd_get_row_status(col); | ||
203 | for (row = 0; row < KB_ROWS; row++) { | ||
204 | unsigned int scancode, pressed; | ||
205 | |||
206 | scancode = SCANCODE(row, col); | ||
207 | pressed = rowd & KB_ROWMASK(row); | ||
208 | |||
209 | input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); | ||
210 | |||
211 | if (pressed) | ||
212 | num_pressed++; | ||
213 | } | ||
214 | spitzkbd_reset_col(col); | ||
215 | } | ||
216 | |||
217 | spitzkbd_activate_all(); | ||
218 | |||
219 | input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); | ||
220 | input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); | ||
221 | |||
222 | if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { | ||
223 | input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); | ||
224 | spitzkbd_data->suspend_jiffies = jiffies; | ||
225 | } | ||
226 | |||
227 | input_sync(spitzkbd_data->input); | ||
228 | |||
229 | /* if any keys are pressed, enable the timer */ | ||
230 | if (num_pressed) | ||
231 | mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
232 | |||
233 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * spitz keyboard interrupt handler. | ||
238 | */ | ||
239 | static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) | ||
240 | { | ||
241 | struct spitzkbd *spitzkbd_data = dev_id; | ||
242 | |||
243 | if (!timer_pending(&spitzkbd_data->timer)) { | ||
244 | /** wait chattering delay **/ | ||
245 | udelay(20); | ||
246 | spitzkbd_scankeyboard(spitzkbd_data); | ||
247 | } | ||
248 | |||
249 | return IRQ_HANDLED; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * spitz timer checking for released keys | ||
254 | */ | ||
255 | static void spitzkbd_timer_callback(unsigned long data) | ||
256 | { | ||
257 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
258 | |||
259 | spitzkbd_scankeyboard(spitzkbd_data); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * The hinge switches generate an interrupt. | ||
264 | * We debounce the switches and pass them to the input system. | ||
265 | */ | ||
266 | |||
267 | static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) | ||
268 | { | ||
269 | struct spitzkbd *spitzkbd_data = dev_id; | ||
270 | |||
271 | if (!timer_pending(&spitzkbd_data->htimer)) | ||
272 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
273 | |||
274 | return IRQ_HANDLED; | ||
275 | } | ||
276 | |||
277 | #define HINGE_STABLE_COUNT 2 | ||
278 | static int sharpsl_hinge_state; | ||
279 | static int hinge_count; | ||
280 | |||
281 | static void spitzkbd_hinge_timer(unsigned long data) | ||
282 | { | ||
283 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
284 | unsigned long state; | ||
285 | unsigned long flags; | ||
286 | |||
287 | state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); | ||
288 | state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); | ||
289 | if (state != sharpsl_hinge_state) { | ||
290 | hinge_count = 0; | ||
291 | sharpsl_hinge_state = state; | ||
292 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
293 | hinge_count++; | ||
294 | } | ||
295 | |||
296 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
297 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
298 | |||
299 | input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); | ||
300 | input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); | ||
301 | input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); | ||
302 | input_sync(spitzkbd_data->input); | ||
303 | |||
304 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
305 | } else { | ||
306 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | #ifdef CONFIG_PM | ||
311 | static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) | ||
312 | { | ||
313 | int i; | ||
314 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
315 | spitzkbd->suspended = 1; | ||
316 | |||
317 | /* Set Strobe lines as inputs - *except* strobe line 0 leave this | ||
318 | enabled so we can detect a power button press for resume */ | ||
319 | for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) | ||
320 | pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int spitzkbd_resume(struct platform_device *dev) | ||
326 | { | ||
327 | int i; | ||
328 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
329 | |||
330 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
331 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
332 | |||
333 | /* Upon resume, ignore the suspend key for a short while */ | ||
334 | spitzkbd->suspend_jiffies = jiffies; | ||
335 | spitzkbd->suspended = 0; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | #else | ||
340 | #define spitzkbd_suspend NULL | ||
341 | #define spitzkbd_resume NULL | ||
342 | #endif | ||
343 | |||
344 | static int __devinit spitzkbd_probe(struct platform_device *dev) | ||
345 | { | ||
346 | struct spitzkbd *spitzkbd; | ||
347 | struct input_dev *input_dev; | ||
348 | int i, err = -ENOMEM; | ||
349 | |||
350 | spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); | ||
351 | input_dev = input_allocate_device(); | ||
352 | if (!spitzkbd || !input_dev) | ||
353 | goto fail; | ||
354 | |||
355 | platform_set_drvdata(dev, spitzkbd); | ||
356 | strcpy(spitzkbd->phys, "spitzkbd/input0"); | ||
357 | |||
358 | spin_lock_init(&spitzkbd->lock); | ||
359 | |||
360 | /* Init Keyboard rescan timer */ | ||
361 | init_timer(&spitzkbd->timer); | ||
362 | spitzkbd->timer.function = spitzkbd_timer_callback; | ||
363 | spitzkbd->timer.data = (unsigned long) spitzkbd; | ||
364 | |||
365 | /* Init Hinge Timer */ | ||
366 | init_timer(&spitzkbd->htimer); | ||
367 | spitzkbd->htimer.function = spitzkbd_hinge_timer; | ||
368 | spitzkbd->htimer.data = (unsigned long) spitzkbd; | ||
369 | |||
370 | spitzkbd->suspend_jiffies = jiffies; | ||
371 | |||
372 | spitzkbd->input = input_dev; | ||
373 | |||
374 | input_dev->name = "Spitz Keyboard"; | ||
375 | input_dev->phys = spitzkbd->phys; | ||
376 | input_dev->dev.parent = &dev->dev; | ||
377 | |||
378 | input_dev->id.bustype = BUS_HOST; | ||
379 | input_dev->id.vendor = 0x0001; | ||
380 | input_dev->id.product = 0x0001; | ||
381 | input_dev->id.version = 0x0100; | ||
382 | |||
383 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
384 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
385 | input_dev->keycode = spitzkbd->keycode; | ||
386 | input_dev->keycodesize = sizeof(unsigned char); | ||
387 | input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); | ||
388 | |||
389 | memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); | ||
390 | for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) | ||
391 | set_bit(spitzkbd->keycode[i], input_dev->keybit); | ||
392 | clear_bit(0, input_dev->keybit); | ||
393 | set_bit(KEY_SUSPEND, input_dev->keybit); | ||
394 | set_bit(SW_LID, input_dev->swbit); | ||
395 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
396 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
397 | |||
398 | err = input_register_device(input_dev); | ||
399 | if (err) | ||
400 | goto fail; | ||
401 | |||
402 | mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
403 | |||
404 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
405 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { | ||
406 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); | ||
407 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, | ||
408 | IRQF_DISABLED|IRQF_TRIGGER_RISING, | ||
409 | "Spitzkbd Sense", spitzkbd)) | ||
410 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); | ||
411 | } | ||
412 | |||
413 | /* Set Strobe lines as outputs - set high */ | ||
414 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
415 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
416 | |||
417 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
418 | pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); | ||
419 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); | ||
420 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); | ||
421 | |||
422 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, | ||
423 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
424 | "Spitzkbd Sync", spitzkbd); | ||
425 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, | ||
426 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
427 | "Spitzkbd PwrOn", spitzkbd); | ||
428 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, | ||
429 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
430 | "Spitzkbd SWA", spitzkbd); | ||
431 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, | ||
432 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
433 | "Spitzkbd SWB", spitzkbd); | ||
434 | request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, | ||
435 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
436 | "Spitzkbd HP", spitzkbd); | ||
437 | |||
438 | return 0; | ||
439 | |||
440 | fail: input_free_device(input_dev); | ||
441 | kfree(spitzkbd); | ||
442 | return err; | ||
443 | } | ||
444 | |||
445 | static int __devexit spitzkbd_remove(struct platform_device *dev) | ||
446 | { | ||
447 | int i; | ||
448 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
449 | |||
450 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) | ||
451 | free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); | ||
452 | |||
453 | free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); | ||
454 | free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); | ||
455 | free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); | ||
456 | free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); | ||
457 | free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); | ||
458 | |||
459 | del_timer_sync(&spitzkbd->htimer); | ||
460 | del_timer_sync(&spitzkbd->timer); | ||
461 | |||
462 | input_unregister_device(spitzkbd->input); | ||
463 | |||
464 | kfree(spitzkbd); | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct platform_driver spitzkbd_driver = { | ||
470 | .probe = spitzkbd_probe, | ||
471 | .remove = __devexit_p(spitzkbd_remove), | ||
472 | .suspend = spitzkbd_suspend, | ||
473 | .resume = spitzkbd_resume, | ||
474 | .driver = { | ||
475 | .name = "spitz-keyboard", | ||
476 | .owner = THIS_MODULE, | ||
477 | }, | ||
478 | }; | ||
479 | |||
480 | static int __init spitzkbd_init(void) | ||
481 | { | ||
482 | return platform_driver_register(&spitzkbd_driver); | ||
483 | } | ||
484 | |||
485 | static void __exit spitzkbd_exit(void) | ||
486 | { | ||
487 | platform_driver_unregister(&spitzkbd_driver); | ||
488 | } | ||
489 | |||
490 | module_init(spitzkbd_init); | ||
491 | module_exit(spitzkbd_exit); | ||
492 | |||
493 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
494 | MODULE_DESCRIPTION("Spitz Keyboard Driver"); | ||
495 | MODULE_LICENSE("GPL v2"); | ||
496 | MODULE_ALIAS("platform:spitz-keyboard"); | ||
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c new file mode 100644 index 00000000000..493c93f25e2 --- /dev/null +++ b/drivers/input/keyboard/tca6416-keypad.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * Driver for keys on TCA6416 I2C IO expander | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * | ||
6 | * Author : Sriramakrishnan.A.G. <srk@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/input.h> | ||
23 | #include <linux/tca6416_keypad.h> | ||
24 | |||
25 | #define TCA6416_INPUT 0 | ||
26 | #define TCA6416_OUTPUT 1 | ||
27 | #define TCA6416_INVERT 2 | ||
28 | #define TCA6416_DIRECTION 3 | ||
29 | |||
30 | static const struct i2c_device_id tca6416_id[] = { | ||
31 | { "tca6416-keys", 16, }, | ||
32 | { } | ||
33 | }; | ||
34 | MODULE_DEVICE_TABLE(i2c, tca6416_id); | ||
35 | |||
36 | struct tca6416_drv_data { | ||
37 | struct input_dev *input; | ||
38 | struct tca6416_button data[0]; | ||
39 | }; | ||
40 | |||
41 | struct tca6416_keypad_chip { | ||
42 | uint16_t reg_output; | ||
43 | uint16_t reg_direction; | ||
44 | uint16_t reg_input; | ||
45 | |||
46 | struct i2c_client *client; | ||
47 | struct input_dev *input; | ||
48 | struct delayed_work dwork; | ||
49 | u16 pinmask; | ||
50 | int irqnum; | ||
51 | bool use_polling; | ||
52 | struct tca6416_button buttons[0]; | ||
53 | }; | ||
54 | |||
55 | static int tca6416_write_reg(struct tca6416_keypad_chip *chip, int reg, u16 val) | ||
56 | { | ||
57 | int error; | ||
58 | |||
59 | error = i2c_smbus_write_word_data(chip->client, reg << 1, val); | ||
60 | if (error < 0) { | ||
61 | dev_err(&chip->client->dev, | ||
62 | "%s failed, reg: %d, val: %d, error: %d\n", | ||
63 | __func__, reg, val, error); | ||
64 | return error; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int tca6416_read_reg(struct tca6416_keypad_chip *chip, int reg, u16 *val) | ||
71 | { | ||
72 | int retval; | ||
73 | |||
74 | retval = i2c_smbus_read_word_data(chip->client, reg << 1); | ||
75 | if (retval < 0) { | ||
76 | dev_err(&chip->client->dev, "%s failed, reg: %d, error: %d\n", | ||
77 | __func__, reg, retval); | ||
78 | return retval; | ||
79 | } | ||
80 | |||
81 | *val = (u16)retval; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static void tca6416_keys_scan(struct tca6416_keypad_chip *chip) | ||
86 | { | ||
87 | struct input_dev *input = chip->input; | ||
88 | u16 reg_val, val; | ||
89 | int error, i, pin_index; | ||
90 | |||
91 | error = tca6416_read_reg(chip, TCA6416_INPUT, ®_val); | ||
92 | if (error) | ||
93 | return; | ||
94 | |||
95 | reg_val &= chip->pinmask; | ||
96 | |||
97 | /* Figure out which lines have changed */ | ||
98 | val = reg_val ^ chip->reg_input; | ||
99 | chip->reg_input = reg_val; | ||
100 | |||
101 | for (i = 0, pin_index = 0; i < 16; i++) { | ||
102 | if (val & (1 << i)) { | ||
103 | struct tca6416_button *button = &chip->buttons[pin_index]; | ||
104 | unsigned int type = button->type ?: EV_KEY; | ||
105 | int state = ((reg_val & (1 << i)) ? 1 : 0) | ||
106 | ^ button->active_low; | ||
107 | |||
108 | input_event(input, type, button->code, !!state); | ||
109 | input_sync(input); | ||
110 | } | ||
111 | |||
112 | if (chip->pinmask & (1 << i)) | ||
113 | pin_index++; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * This is threaded IRQ handler and this can (and will) sleep. | ||
119 | */ | ||
120 | static irqreturn_t tca6416_keys_isr(int irq, void *dev_id) | ||
121 | { | ||
122 | struct tca6416_keypad_chip *chip = dev_id; | ||
123 | |||
124 | tca6416_keys_scan(chip); | ||
125 | |||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | |||
129 | static void tca6416_keys_work_func(struct work_struct *work) | ||
130 | { | ||
131 | struct tca6416_keypad_chip *chip = | ||
132 | container_of(work, struct tca6416_keypad_chip, dwork.work); | ||
133 | |||
134 | tca6416_keys_scan(chip); | ||
135 | schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); | ||
136 | } | ||
137 | |||
138 | static int tca6416_keys_open(struct input_dev *dev) | ||
139 | { | ||
140 | struct tca6416_keypad_chip *chip = input_get_drvdata(dev); | ||
141 | |||
142 | /* Get initial device state in case it has switches */ | ||
143 | tca6416_keys_scan(chip); | ||
144 | |||
145 | if (chip->use_polling) | ||
146 | schedule_delayed_work(&chip->dwork, msecs_to_jiffies(100)); | ||
147 | else | ||
148 | enable_irq(chip->irqnum); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void tca6416_keys_close(struct input_dev *dev) | ||
154 | { | ||
155 | struct tca6416_keypad_chip *chip = input_get_drvdata(dev); | ||
156 | |||
157 | if (chip->use_polling) | ||
158 | cancel_delayed_work_sync(&chip->dwork); | ||
159 | else | ||
160 | disable_irq(chip->irqnum); | ||
161 | } | ||
162 | |||
163 | static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip) | ||
164 | { | ||
165 | int error; | ||
166 | |||
167 | error = tca6416_read_reg(chip, TCA6416_OUTPUT, &chip->reg_output); | ||
168 | if (error) | ||
169 | return error; | ||
170 | |||
171 | error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); | ||
172 | if (error) | ||
173 | return error; | ||
174 | |||
175 | /* ensure that keypad pins are set to input */ | ||
176 | error = tca6416_write_reg(chip, TCA6416_DIRECTION, | ||
177 | chip->reg_direction | chip->pinmask); | ||
178 | if (error) | ||
179 | return error; | ||
180 | |||
181 | error = tca6416_read_reg(chip, TCA6416_DIRECTION, &chip->reg_direction); | ||
182 | if (error) | ||
183 | return error; | ||
184 | |||
185 | error = tca6416_read_reg(chip, TCA6416_INPUT, &chip->reg_input); | ||
186 | if (error) | ||
187 | return error; | ||
188 | |||
189 | chip->reg_input &= chip->pinmask; | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int __devinit tca6416_keypad_probe(struct i2c_client *client, | ||
195 | const struct i2c_device_id *id) | ||
196 | { | ||
197 | struct tca6416_keys_platform_data *pdata; | ||
198 | struct tca6416_keypad_chip *chip; | ||
199 | struct input_dev *input; | ||
200 | int error; | ||
201 | int i; | ||
202 | |||
203 | /* Check functionality */ | ||
204 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { | ||
205 | dev_err(&client->dev, "%s adapter not supported\n", | ||
206 | dev_driver_string(&client->adapter->dev)); | ||
207 | return -ENODEV; | ||
208 | } | ||
209 | |||
210 | pdata = client->dev.platform_data; | ||
211 | if (!pdata) { | ||
212 | dev_dbg(&client->dev, "no platform data\n"); | ||
213 | return -EINVAL; | ||
214 | } | ||
215 | |||
216 | chip = kzalloc(sizeof(struct tca6416_keypad_chip) + | ||
217 | pdata->nbuttons * sizeof(struct tca6416_button), | ||
218 | GFP_KERNEL); | ||
219 | input = input_allocate_device(); | ||
220 | if (!chip || !input) { | ||
221 | error = -ENOMEM; | ||
222 | goto fail1; | ||
223 | } | ||
224 | |||
225 | chip->client = client; | ||
226 | chip->input = input; | ||
227 | chip->pinmask = pdata->pinmask; | ||
228 | chip->use_polling = pdata->use_polling; | ||
229 | |||
230 | INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func); | ||
231 | |||
232 | input->phys = "tca6416-keys/input0"; | ||
233 | input->name = client->name; | ||
234 | input->dev.parent = &client->dev; | ||
235 | |||
236 | input->open = tca6416_keys_open; | ||
237 | input->close = tca6416_keys_close; | ||
238 | |||
239 | input->id.bustype = BUS_HOST; | ||
240 | input->id.vendor = 0x0001; | ||
241 | input->id.product = 0x0001; | ||
242 | input->id.version = 0x0100; | ||
243 | |||
244 | /* Enable auto repeat feature of Linux input subsystem */ | ||
245 | if (pdata->rep) | ||
246 | __set_bit(EV_REP, input->evbit); | ||
247 | |||
248 | for (i = 0; i < pdata->nbuttons; i++) { | ||
249 | unsigned int type; | ||
250 | |||
251 | chip->buttons[i] = pdata->buttons[i]; | ||
252 | type = (pdata->buttons[i].type) ?: EV_KEY; | ||
253 | input_set_capability(input, type, pdata->buttons[i].code); | ||
254 | } | ||
255 | |||
256 | input_set_drvdata(input, chip); | ||
257 | |||
258 | /* | ||
259 | * Initialize cached registers from their original values. | ||
260 | * we can't share this chip with another i2c master. | ||
261 | */ | ||
262 | error = tca6416_setup_registers(chip); | ||
263 | if (error) | ||
264 | goto fail1; | ||
265 | |||
266 | if (!chip->use_polling) { | ||
267 | if (pdata->irq_is_gpio) | ||
268 | chip->irqnum = gpio_to_irq(client->irq); | ||
269 | else | ||
270 | chip->irqnum = client->irq; | ||
271 | |||
272 | error = request_threaded_irq(chip->irqnum, NULL, | ||
273 | tca6416_keys_isr, | ||
274 | IRQF_TRIGGER_FALLING, | ||
275 | "tca6416-keypad", chip); | ||
276 | if (error) { | ||
277 | dev_dbg(&client->dev, | ||
278 | "Unable to claim irq %d; error %d\n", | ||
279 | chip->irqnum, error); | ||
280 | goto fail1; | ||
281 | } | ||
282 | disable_irq(chip->irqnum); | ||
283 | } | ||
284 | |||
285 | error = input_register_device(input); | ||
286 | if (error) { | ||
287 | dev_dbg(&client->dev, | ||
288 | "Unable to register input device, error: %d\n", error); | ||
289 | goto fail2; | ||
290 | } | ||
291 | |||
292 | i2c_set_clientdata(client, chip); | ||
293 | |||
294 | return 0; | ||
295 | |||
296 | fail2: | ||
297 | if (!chip->use_polling) { | ||
298 | free_irq(chip->irqnum, chip); | ||
299 | enable_irq(chip->irqnum); | ||
300 | } | ||
301 | fail1: | ||
302 | input_free_device(input); | ||
303 | kfree(chip); | ||
304 | return error; | ||
305 | } | ||
306 | |||
307 | static int __devexit tca6416_keypad_remove(struct i2c_client *client) | ||
308 | { | ||
309 | struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); | ||
310 | |||
311 | if (!chip->use_polling) { | ||
312 | free_irq(chip->irqnum, chip); | ||
313 | enable_irq(chip->irqnum); | ||
314 | } | ||
315 | |||
316 | input_unregister_device(chip->input); | ||
317 | kfree(chip); | ||
318 | |||
319 | i2c_set_clientdata(client, NULL); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | |||
325 | static struct i2c_driver tca6416_keypad_driver = { | ||
326 | .driver = { | ||
327 | .name = "tca6416-keypad", | ||
328 | }, | ||
329 | .probe = tca6416_keypad_probe, | ||
330 | .remove = __devexit_p(tca6416_keypad_remove), | ||
331 | .id_table = tca6416_id, | ||
332 | }; | ||
333 | |||
334 | static int __init tca6416_keypad_init(void) | ||
335 | { | ||
336 | return i2c_add_driver(&tca6416_keypad_driver); | ||
337 | } | ||
338 | |||
339 | subsys_initcall(tca6416_keypad_init); | ||
340 | |||
341 | static void __exit tca6416_keypad_exit(void) | ||
342 | { | ||
343 | i2c_del_driver(&tca6416_keypad_driver); | ||
344 | } | ||
345 | module_exit(tca6416_keypad_exit); | ||
346 | |||
347 | MODULE_AUTHOR("Sriramakrishnan <srk@ti.com>"); | ||
348 | MODULE_DESCRIPTION("Keypad driver over tca6146 IO expander"); | ||
349 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f269cfc..00000000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null | |||
@@ -1,431 +0,0 @@ | |||
1 | /* | ||
2 | * Keyboard driver for Sharp Tosa models (SL-6000x) | ||
3 | * | ||
4 | * Copyright (c) 2005 Dirk Opfer | ||
5 | * Copyright (c) 2007 Dmitry Baryshkov | ||
6 | * | ||
7 | * Based on xtkbd.c/locomkbd.c/corgikbd.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <mach/gpio.h> | ||
24 | #include <mach/tosa.h> | ||
25 | |||
26 | #define KB_ROWMASK(r) (1 << (r)) | ||
27 | #define SCANCODE(r, c) (((r)<<4) + (c) + 1) | ||
28 | #define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 | ||
29 | |||
30 | #define SCAN_INTERVAL (HZ/10) | ||
31 | |||
32 | #define KB_DISCHARGE_DELAY 10 | ||
33 | #define KB_ACTIVATE_DELAY 10 | ||
34 | |||
35 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { | ||
36 | 0, | ||
37 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | ||
38 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
39 | KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, | ||
40 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
41 | KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, | ||
42 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
43 | KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, | ||
44 | KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, | ||
45 | KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, | ||
46 | 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, | ||
47 | KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, | ||
48 | 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, | ||
49 | KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, | ||
50 | 0, 0, 0, | ||
51 | }; | ||
52 | |||
53 | struct tosakbd { | ||
54 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; | ||
55 | struct input_dev *input; | ||
56 | bool suspended; | ||
57 | spinlock_t lock; /* protect kbd scanning */ | ||
58 | struct timer_list timer; | ||
59 | }; | ||
60 | |||
61 | |||
62 | /* Helper functions for reading the keyboard matrix | ||
63 | * Note: We should really be using the generic gpio functions to alter | ||
64 | * GPDR but it requires a function call per GPIO bit which is | ||
65 | * excessive when we need to access 12 bits at once, multiple times. | ||
66 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
67 | * or similar. | ||
68 | */ | ||
69 | #define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) | ||
70 | |||
71 | static inline void tosakbd_discharge_all(void) | ||
72 | { | ||
73 | /* STROBE All HiZ */ | ||
74 | GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
75 | GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; | ||
76 | GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
77 | GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; | ||
78 | } | ||
79 | |||
80 | static inline void tosakbd_activate_all(void) | ||
81 | { | ||
82 | /* STROBE ALL -> High */ | ||
83 | GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
84 | GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; | ||
85 | GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
86 | GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; | ||
87 | |||
88 | udelay(KB_DISCHARGE_DELAY); | ||
89 | |||
90 | /* STATE CLEAR */ | ||
91 | GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; | ||
92 | } | ||
93 | |||
94 | static inline void tosakbd_activate_col(int col) | ||
95 | { | ||
96 | if (col <= 5) { | ||
97 | /* STROBE col -> High, not col -> HiZ */ | ||
98 | GPSR1 = TOSA_GPIO_STROBE_BIT(col); | ||
99 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
100 | } else { | ||
101 | /* STROBE col -> High, not col -> HiZ */ | ||
102 | GPSR2 = TOSA_GPIO_STROBE_BIT(col); | ||
103 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static inline void tosakbd_reset_col(int col) | ||
108 | { | ||
109 | if (col <= 5) { | ||
110 | /* STROBE col -> Low */ | ||
111 | GPCR1 = TOSA_GPIO_STROBE_BIT(col); | ||
112 | /* STROBE col -> out, not col -> HiZ */ | ||
113 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
114 | } else { | ||
115 | /* STROBE col -> Low */ | ||
116 | GPCR2 = TOSA_GPIO_STROBE_BIT(col); | ||
117 | /* STROBE col -> out, not col -> HiZ */ | ||
118 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
119 | } | ||
120 | } | ||
121 | /* | ||
122 | * The tosa keyboard only generates interrupts when a key is pressed. | ||
123 | * So when a key is pressed, we enable a timer. This timer scans the | ||
124 | * keyboard, and this is how we detect when the key is released. | ||
125 | */ | ||
126 | |||
127 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
128 | static void tosakbd_scankeyboard(struct platform_device *dev) | ||
129 | { | ||
130 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
131 | unsigned int row, col, rowd; | ||
132 | unsigned long flags; | ||
133 | unsigned int num_pressed = 0; | ||
134 | |||
135 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
136 | |||
137 | if (tosakbd->suspended) | ||
138 | goto out; | ||
139 | |||
140 | for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { | ||
141 | /* | ||
142 | * Discharge the output driver capacitatance | ||
143 | * in the keyboard matrix. (Yes it is significant..) | ||
144 | */ | ||
145 | tosakbd_discharge_all(); | ||
146 | udelay(KB_DISCHARGE_DELAY); | ||
147 | |||
148 | tosakbd_activate_col(col); | ||
149 | udelay(KB_ACTIVATE_DELAY); | ||
150 | |||
151 | rowd = GET_ROWS_STATUS(col); | ||
152 | |||
153 | for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { | ||
154 | unsigned int scancode, pressed; | ||
155 | scancode = SCANCODE(row, col); | ||
156 | pressed = rowd & KB_ROWMASK(row); | ||
157 | |||
158 | if (pressed && !tosakbd->keycode[scancode]) | ||
159 | dev_warn(&dev->dev, | ||
160 | "unhandled scancode: 0x%02x\n", | ||
161 | scancode); | ||
162 | |||
163 | input_report_key(tosakbd->input, | ||
164 | tosakbd->keycode[scancode], | ||
165 | pressed); | ||
166 | if (pressed) | ||
167 | num_pressed++; | ||
168 | } | ||
169 | |||
170 | tosakbd_reset_col(col); | ||
171 | } | ||
172 | |||
173 | tosakbd_activate_all(); | ||
174 | |||
175 | input_sync(tosakbd->input); | ||
176 | |||
177 | /* if any keys are pressed, enable the timer */ | ||
178 | if (num_pressed) | ||
179 | mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); | ||
180 | |||
181 | out: | ||
182 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * tosa keyboard interrupt handler. | ||
187 | */ | ||
188 | static irqreturn_t tosakbd_interrupt(int irq, void *__dev) | ||
189 | { | ||
190 | struct platform_device *dev = __dev; | ||
191 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
192 | |||
193 | if (!timer_pending(&tosakbd->timer)) { | ||
194 | /** wait chattering delay **/ | ||
195 | udelay(20); | ||
196 | tosakbd_scankeyboard(dev); | ||
197 | } | ||
198 | |||
199 | return IRQ_HANDLED; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * tosa timer checking for released keys | ||
204 | */ | ||
205 | static void tosakbd_timer_callback(unsigned long __dev) | ||
206 | { | ||
207 | struct platform_device *dev = (struct platform_device *)__dev; | ||
208 | |||
209 | tosakbd_scankeyboard(dev); | ||
210 | } | ||
211 | |||
212 | #ifdef CONFIG_PM | ||
213 | static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | ||
214 | { | ||
215 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
216 | unsigned long flags; | ||
217 | |||
218 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
219 | tosakbd->suspended = true; | ||
220 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
221 | |||
222 | del_timer_sync(&tosakbd->timer); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int tosakbd_resume(struct platform_device *dev) | ||
228 | { | ||
229 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
230 | |||
231 | tosakbd->suspended = false; | ||
232 | tosakbd_scankeyboard(dev); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | #else | ||
237 | #define tosakbd_suspend NULL | ||
238 | #define tosakbd_resume NULL | ||
239 | #endif | ||
240 | |||
241 | static int __devinit tosakbd_probe(struct platform_device *pdev) { | ||
242 | |||
243 | int i; | ||
244 | struct tosakbd *tosakbd; | ||
245 | struct input_dev *input_dev; | ||
246 | int error; | ||
247 | |||
248 | tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); | ||
249 | if (!tosakbd) | ||
250 | return -ENOMEM; | ||
251 | |||
252 | input_dev = input_allocate_device(); | ||
253 | if (!input_dev) { | ||
254 | kfree(tosakbd); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | platform_set_drvdata(pdev, tosakbd); | ||
259 | |||
260 | spin_lock_init(&tosakbd->lock); | ||
261 | |||
262 | /* Init Keyboard rescan timer */ | ||
263 | init_timer(&tosakbd->timer); | ||
264 | tosakbd->timer.function = tosakbd_timer_callback; | ||
265 | tosakbd->timer.data = (unsigned long) pdev; | ||
266 | |||
267 | tosakbd->input = input_dev; | ||
268 | |||
269 | input_set_drvdata(input_dev, tosakbd); | ||
270 | input_dev->name = "Tosa Keyboard"; | ||
271 | input_dev->phys = "tosakbd/input0"; | ||
272 | input_dev->dev.parent = &pdev->dev; | ||
273 | |||
274 | input_dev->id.bustype = BUS_HOST; | ||
275 | input_dev->id.vendor = 0x0001; | ||
276 | input_dev->id.product = 0x0001; | ||
277 | input_dev->id.version = 0x0100; | ||
278 | |||
279 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
280 | input_dev->keycode = tosakbd->keycode; | ||
281 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); | ||
282 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | ||
283 | |||
284 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | ||
285 | |||
286 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | ||
287 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | ||
288 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
289 | |||
290 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
291 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
292 | int gpio = TOSA_GPIO_KEY_SENSE(i); | ||
293 | int irq; | ||
294 | error = gpio_request(gpio, "tosakbd"); | ||
295 | if (error < 0) { | ||
296 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
297 | " error %d\n", gpio, error); | ||
298 | goto fail; | ||
299 | } | ||
300 | |||
301 | error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); | ||
302 | if (error < 0) { | ||
303 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
304 | " direction for GPIO %d, error %d\n", | ||
305 | gpio, error); | ||
306 | gpio_free(gpio); | ||
307 | goto fail; | ||
308 | } | ||
309 | |||
310 | irq = gpio_to_irq(gpio); | ||
311 | if (irq < 0) { | ||
312 | error = irq; | ||
313 | printk(KERN_ERR "gpio-keys: Unable to get irq number" | ||
314 | " for GPIO %d, error %d\n", | ||
315 | gpio, error); | ||
316 | gpio_free(gpio); | ||
317 | goto fail; | ||
318 | } | ||
319 | |||
320 | error = request_irq(irq, tosakbd_interrupt, | ||
321 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
322 | "tosakbd", pdev); | ||
323 | |||
324 | if (error) { | ||
325 | printk("tosakbd: Can't get IRQ: %d: error %d!\n", | ||
326 | irq, error); | ||
327 | gpio_free(gpio); | ||
328 | goto fail; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* Set Strobe lines as outputs - set high */ | ||
333 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { | ||
334 | int gpio = TOSA_GPIO_KEY_STROBE(i); | ||
335 | error = gpio_request(gpio, "tosakbd"); | ||
336 | if (error < 0) { | ||
337 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
338 | " error %d\n", gpio, error); | ||
339 | goto fail2; | ||
340 | } | ||
341 | |||
342 | error = gpio_direction_output(gpio, 1); | ||
343 | if (error < 0) { | ||
344 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
345 | " direction for GPIO %d, error %d\n", | ||
346 | gpio, error); | ||
347 | gpio_free(gpio); | ||
348 | goto fail2; | ||
349 | } | ||
350 | |||
351 | } | ||
352 | |||
353 | error = input_register_device(input_dev); | ||
354 | if (error) { | ||
355 | printk(KERN_ERR "tosakbd: Unable to register input device, " | ||
356 | "error: %d\n", error); | ||
357 | goto fail2; | ||
358 | } | ||
359 | |||
360 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | ||
361 | |||
362 | return 0; | ||
363 | |||
364 | fail2: | ||
365 | while (--i >= 0) | ||
366 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
367 | |||
368 | i = TOSA_KEY_SENSE_NUM; | ||
369 | fail: | ||
370 | while (--i >= 0) { | ||
371 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); | ||
372 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
373 | } | ||
374 | |||
375 | platform_set_drvdata(pdev, NULL); | ||
376 | input_free_device(input_dev); | ||
377 | kfree(tosakbd); | ||
378 | |||
379 | return error; | ||
380 | } | ||
381 | |||
382 | static int __devexit tosakbd_remove(struct platform_device *dev) | ||
383 | { | ||
384 | int i; | ||
385 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
386 | |||
387 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) | ||
388 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
389 | |||
390 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
391 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); | ||
392 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
393 | } | ||
394 | |||
395 | del_timer_sync(&tosakbd->timer); | ||
396 | |||
397 | input_unregister_device(tosakbd->input); | ||
398 | |||
399 | kfree(tosakbd); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static struct platform_driver tosakbd_driver = { | ||
405 | .probe = tosakbd_probe, | ||
406 | .remove = __devexit_p(tosakbd_remove), | ||
407 | .suspend = tosakbd_suspend, | ||
408 | .resume = tosakbd_resume, | ||
409 | .driver = { | ||
410 | .name = "tosa-keyboard", | ||
411 | .owner = THIS_MODULE, | ||
412 | }, | ||
413 | }; | ||
414 | |||
415 | static int __devinit tosakbd_init(void) | ||
416 | { | ||
417 | return platform_driver_register(&tosakbd_driver); | ||
418 | } | ||
419 | |||
420 | static void __exit tosakbd_exit(void) | ||
421 | { | ||
422 | platform_driver_unregister(&tosakbd_driver); | ||
423 | } | ||
424 | |||
425 | module_init(tosakbd_init); | ||
426 | module_exit(tosakbd_exit); | ||
427 | |||
428 | MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); | ||
429 | MODULE_DESCRIPTION("Tosa Keyboard Driver"); | ||
430 | MODULE_LICENSE("GPL v2"); | ||
431 | MODULE_ALIAS("platform:tosa-keyboard"); | ||
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index 40dabd8487b..4cc82826ea6 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c | |||
@@ -87,7 +87,6 @@ static int __devinit pm860x_onkey_probe(struct platform_device *pdev) | |||
87 | info->idev->phys = "88pm860x_on/input0"; | 87 | info->idev->phys = "88pm860x_on/input0"; |
88 | info->idev->id.bustype = BUS_I2C; | 88 | info->idev->id.bustype = BUS_I2C; |
89 | info->idev->dev.parent = &pdev->dev; | 89 | info->idev->dev.parent = &pdev->dev; |
90 | info->irq = irq; | ||
91 | info->idev->evbit[0] = BIT_MASK(EV_KEY); | 90 | info->idev->evbit[0] = BIT_MASK(EV_KEY); |
92 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | 91 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); |
93 | 92 | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 23140a3bb8e..48cdabec372 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -22,6 +22,36 @@ config INPUT_88PM860X_ONKEY | |||
22 | To compile this driver as a module, choose M here: the module | 22 | To compile this driver as a module, choose M here: the module |
23 | will be called 88pm860x_onkey. | 23 | will be called 88pm860x_onkey. |
24 | 24 | ||
25 | config INPUT_AD714X | ||
26 | tristate "Analog Devices AD714x Capacitance Touch Sensor" | ||
27 | help | ||
28 | Say Y here if you want to support an AD7142/3/7/8/7A touch sensor. | ||
29 | |||
30 | You should select a bus connection too. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the | ||
33 | module will be called ad714x. | ||
34 | |||
35 | config INPUT_AD714X_I2C | ||
36 | tristate "support I2C bus connection" | ||
37 | depends on INPUT_AD714X && I2C | ||
38 | default y | ||
39 | help | ||
40 | Say Y here if you have AD7142/AD7147 hooked to an I2C bus. | ||
41 | |||
42 | To compile this driver as a module, choose M here: the | ||
43 | module will be called ad714x-i2c. | ||
44 | |||
45 | config INPUT_AD714X_SPI | ||
46 | tristate "support SPI bus connection" | ||
47 | depends on INPUT_AD714X && SPI | ||
48 | default y | ||
49 | help | ||
50 | Say Y here if you have AD7142/AD7147 hooked to a SPI bus. | ||
51 | |||
52 | To compile this driver as a module, choose M here: the | ||
53 | module will be called ad714x-spi. | ||
54 | |||
25 | config INPUT_PCSPKR | 55 | config INPUT_PCSPKR |
26 | tristate "PC Speaker support" | 56 | tristate "PC Speaker support" |
27 | depends on PCSPKR_PLATFORM | 57 | depends on PCSPKR_PLATFORM |
@@ -277,6 +307,16 @@ config INPUT_PCF50633_PMU | |||
277 | Say Y to include support for delivering PMU events via input | 307 | Say Y to include support for delivering PMU events via input |
278 | layer on NXP PCF50633. | 308 | layer on NXP PCF50633. |
279 | 309 | ||
310 | config INPUT_PCF8574 | ||
311 | tristate "PCF8574 Keypad input device" | ||
312 | depends on I2C && EXPERIMENTAL | ||
313 | help | ||
314 | Say Y here if you want to support a keypad connetced via I2C | ||
315 | with a PCF8574. | ||
316 | |||
317 | To compile this driver as a module, choose M here: the | ||
318 | module will be called pcf8574_keypad. | ||
319 | |||
280 | config INPUT_GPIO_ROTARY_ENCODER | 320 | config INPUT_GPIO_ROTARY_ENCODER |
281 | tristate "Rotary encoders connected to GPIO pins" | 321 | tristate "Rotary encoders connected to GPIO pins" |
282 | depends on GPIOLIB && GENERIC_GPIO | 322 | depends on GPIOLIB && GENERIC_GPIO |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 7e95a5d474d..f9f577031e0 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -5,6 +5,9 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o | 7 | obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o |
8 | obj-$(CONFIG_INPUT_AD714X) += ad714x.o | ||
9 | obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o | ||
10 | obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o | ||
8 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 11 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
9 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 12 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
10 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 13 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
@@ -19,6 +22,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | |||
19 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 22 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
20 | obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o | 23 | obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o |
21 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 24 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
25 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o | ||
22 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 26 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
23 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 27 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
24 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o | 28 | obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o |
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c new file mode 100644 index 00000000000..e9adbe49f6a --- /dev/null +++ b/drivers/input/misc/ad714x-i2c.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * AD714X CapTouch Programmable Controller driver (I2C bus) | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/input.h> /* BUS_I2C */ | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/types.h> | ||
13 | #include "ad714x.h" | ||
14 | |||
15 | #ifdef CONFIG_PM | ||
16 | static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message) | ||
17 | { | ||
18 | return ad714x_disable(i2c_get_clientdata(client)); | ||
19 | } | ||
20 | |||
21 | static int ad714x_i2c_resume(struct i2c_client *client) | ||
22 | { | ||
23 | return ad714x_enable(i2c_get_clientdata(client)); | ||
24 | } | ||
25 | #else | ||
26 | # define ad714x_i2c_suspend NULL | ||
27 | # define ad714x_i2c_resume NULL | ||
28 | #endif | ||
29 | |||
30 | static int ad714x_i2c_write(struct device *dev, unsigned short reg, | ||
31 | unsigned short data) | ||
32 | { | ||
33 | struct i2c_client *client = to_i2c_client(dev); | ||
34 | int ret = 0; | ||
35 | u8 *_reg = (u8 *)® | ||
36 | u8 *_data = (u8 *)&data; | ||
37 | |||
38 | u8 tx[4] = { | ||
39 | _reg[1], | ||
40 | _reg[0], | ||
41 | _data[1], | ||
42 | _data[0] | ||
43 | }; | ||
44 | |||
45 | ret = i2c_master_send(client, tx, 4); | ||
46 | if (ret < 0) | ||
47 | dev_err(&client->dev, "I2C write error\n"); | ||
48 | |||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | static int ad714x_i2c_read(struct device *dev, unsigned short reg, | ||
53 | unsigned short *data) | ||
54 | { | ||
55 | struct i2c_client *client = to_i2c_client(dev); | ||
56 | int ret = 0; | ||
57 | u8 *_reg = (u8 *)® | ||
58 | u8 *_data = (u8 *)data; | ||
59 | |||
60 | u8 tx[2] = { | ||
61 | _reg[1], | ||
62 | _reg[0] | ||
63 | }; | ||
64 | u8 rx[2]; | ||
65 | |||
66 | ret = i2c_master_send(client, tx, 2); | ||
67 | if (ret >= 0) | ||
68 | ret = i2c_master_recv(client, rx, 2); | ||
69 | |||
70 | if (unlikely(ret < 0)) { | ||
71 | dev_err(&client->dev, "I2C read error\n"); | ||
72 | } else { | ||
73 | _data[0] = rx[1]; | ||
74 | _data[1] = rx[0]; | ||
75 | } | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static int __devinit ad714x_i2c_probe(struct i2c_client *client, | ||
81 | const struct i2c_device_id *id) | ||
82 | { | ||
83 | struct ad714x_chip *chip; | ||
84 | |||
85 | chip = ad714x_probe(&client->dev, BUS_I2C, client->irq, | ||
86 | ad714x_i2c_read, ad714x_i2c_write); | ||
87 | if (IS_ERR(chip)) | ||
88 | return PTR_ERR(chip); | ||
89 | |||
90 | i2c_set_clientdata(client, chip); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int __devexit ad714x_i2c_remove(struct i2c_client *client) | ||
96 | { | ||
97 | struct ad714x_chip *chip = i2c_get_clientdata(client); | ||
98 | |||
99 | ad714x_remove(chip); | ||
100 | i2c_set_clientdata(client, NULL); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static const struct i2c_device_id ad714x_id[] = { | ||
106 | { "ad7142_captouch", 0 }, | ||
107 | { "ad7143_captouch", 0 }, | ||
108 | { "ad7147_captouch", 0 }, | ||
109 | { "ad7147a_captouch", 0 }, | ||
110 | { "ad7148_captouch", 0 }, | ||
111 | { } | ||
112 | }; | ||
113 | MODULE_DEVICE_TABLE(i2c, ad714x_id); | ||
114 | |||
115 | static struct i2c_driver ad714x_i2c_driver = { | ||
116 | .driver = { | ||
117 | .name = "ad714x_captouch", | ||
118 | }, | ||
119 | .probe = ad714x_i2c_probe, | ||
120 | .remove = __devexit_p(ad714x_i2c_remove), | ||
121 | .suspend = ad714x_i2c_suspend, | ||
122 | .resume = ad714x_i2c_resume, | ||
123 | .id_table = ad714x_id, | ||
124 | }; | ||
125 | |||
126 | static __init int ad714x_i2c_init(void) | ||
127 | { | ||
128 | return i2c_add_driver(&ad714x_i2c_driver); | ||
129 | } | ||
130 | module_init(ad714x_i2c_init); | ||
131 | |||
132 | static __exit void ad714x_i2c_exit(void) | ||
133 | { | ||
134 | i2c_del_driver(&ad714x_i2c_driver); | ||
135 | } | ||
136 | module_exit(ad714x_i2c_exit); | ||
137 | |||
138 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor I2C Bus Driver"); | ||
139 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
140 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c new file mode 100644 index 00000000000..7f8dedfd1bf --- /dev/null +++ b/drivers/input/misc/ad714x-spi.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * AD714X CapTouch Programmable Controller driver (SPI bus) | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/input.h> /* BUS_I2C */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/spi/spi.h> | ||
12 | #include <linux/types.h> | ||
13 | #include "ad714x.h" | ||
14 | |||
15 | #define AD714x_SPI_CMD_PREFIX 0xE000 /* bits 15:11 */ | ||
16 | #define AD714x_SPI_READ BIT(10) | ||
17 | |||
18 | #ifdef CONFIG_PM | ||
19 | static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message) | ||
20 | { | ||
21 | return ad714x_disable(spi_get_drvdata(spi)); | ||
22 | } | ||
23 | |||
24 | static int ad714x_spi_resume(struct spi_device *spi) | ||
25 | { | ||
26 | return ad714x_enable(spi_get_drvdata(spi)); | ||
27 | } | ||
28 | #else | ||
29 | # define ad714x_spi_suspend NULL | ||
30 | # define ad714x_spi_resume NULL | ||
31 | #endif | ||
32 | |||
33 | static int ad714x_spi_read(struct device *dev, unsigned short reg, | ||
34 | unsigned short *data) | ||
35 | { | ||
36 | struct spi_device *spi = to_spi_device(dev); | ||
37 | unsigned short tx = AD714x_SPI_CMD_PREFIX | AD714x_SPI_READ | reg; | ||
38 | |||
39 | return spi_write_then_read(spi, (u8 *)&tx, 2, (u8 *)data, 2); | ||
40 | } | ||
41 | |||
42 | static int ad714x_spi_write(struct device *dev, unsigned short reg, | ||
43 | unsigned short data) | ||
44 | { | ||
45 | struct spi_device *spi = to_spi_device(dev); | ||
46 | unsigned short tx[2] = { | ||
47 | AD714x_SPI_CMD_PREFIX | reg, | ||
48 | data | ||
49 | }; | ||
50 | |||
51 | return spi_write(spi, (u8 *)tx, 4); | ||
52 | } | ||
53 | |||
54 | static int __devinit ad714x_spi_probe(struct spi_device *spi) | ||
55 | { | ||
56 | struct ad714x_chip *chip; | ||
57 | |||
58 | chip = ad714x_probe(&spi->dev, BUS_SPI, spi->irq, | ||
59 | ad714x_spi_read, ad714x_spi_write); | ||
60 | if (IS_ERR(chip)) | ||
61 | return PTR_ERR(chip); | ||
62 | |||
63 | spi_set_drvdata(spi, chip); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int __devexit ad714x_spi_remove(struct spi_device *spi) | ||
69 | { | ||
70 | struct ad714x_chip *chip = spi_get_drvdata(spi); | ||
71 | |||
72 | ad714x_remove(chip); | ||
73 | spi_set_drvdata(spi, NULL); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static struct spi_driver ad714x_spi_driver = { | ||
79 | .driver = { | ||
80 | .name = "ad714x_captouch", | ||
81 | .owner = THIS_MODULE, | ||
82 | }, | ||
83 | .probe = ad714x_spi_probe, | ||
84 | .remove = __devexit_p(ad714x_spi_remove), | ||
85 | .suspend = ad714x_spi_suspend, | ||
86 | .resume = ad714x_spi_resume, | ||
87 | }; | ||
88 | |||
89 | static __init int ad714x_spi_init(void) | ||
90 | { | ||
91 | return spi_register_driver(&ad714x_spi_driver); | ||
92 | } | ||
93 | module_init(ad714x_spi_init); | ||
94 | |||
95 | static __exit void ad714x_spi_exit(void) | ||
96 | { | ||
97 | spi_unregister_driver(&ad714x_spi_driver); | ||
98 | } | ||
99 | module_exit(ad714x_spi_exit); | ||
100 | |||
101 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor SPI Bus Driver"); | ||
102 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
103 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c new file mode 100644 index 00000000000..0fe27baf5e7 --- /dev/null +++ b/drivers/input/misc/ad714x.c | |||
@@ -0,0 +1,1347 @@ | |||
1 | /* | ||
2 | * AD714X CapTouch Programmable Controller driver supporting AD7142/3/7/8/7A | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/input/ad714x.h> | ||
15 | #include "ad714x.h" | ||
16 | |||
17 | #define AD714X_PWR_CTRL 0x0 | ||
18 | #define AD714X_STG_CAL_EN_REG 0x1 | ||
19 | #define AD714X_AMB_COMP_CTRL0_REG 0x2 | ||
20 | #define AD714X_PARTID_REG 0x17 | ||
21 | #define AD7142_PARTID 0xE620 | ||
22 | #define AD7143_PARTID 0xE630 | ||
23 | #define AD7147_PARTID 0x1470 | ||
24 | #define AD7148_PARTID 0x1480 | ||
25 | #define AD714X_STAGECFG_REG 0x80 | ||
26 | #define AD714X_SYSCFG_REG 0x0 | ||
27 | |||
28 | #define STG_LOW_INT_EN_REG 0x5 | ||
29 | #define STG_HIGH_INT_EN_REG 0x6 | ||
30 | #define STG_COM_INT_EN_REG 0x7 | ||
31 | #define STG_LOW_INT_STA_REG 0x8 | ||
32 | #define STG_HIGH_INT_STA_REG 0x9 | ||
33 | #define STG_COM_INT_STA_REG 0xA | ||
34 | |||
35 | #define CDC_RESULT_S0 0xB | ||
36 | #define CDC_RESULT_S1 0xC | ||
37 | #define CDC_RESULT_S2 0xD | ||
38 | #define CDC_RESULT_S3 0xE | ||
39 | #define CDC_RESULT_S4 0xF | ||
40 | #define CDC_RESULT_S5 0x10 | ||
41 | #define CDC_RESULT_S6 0x11 | ||
42 | #define CDC_RESULT_S7 0x12 | ||
43 | #define CDC_RESULT_S8 0x13 | ||
44 | #define CDC_RESULT_S9 0x14 | ||
45 | #define CDC_RESULT_S10 0x15 | ||
46 | #define CDC_RESULT_S11 0x16 | ||
47 | |||
48 | #define STAGE0_AMBIENT 0xF1 | ||
49 | #define STAGE1_AMBIENT 0x115 | ||
50 | #define STAGE2_AMBIENT 0x139 | ||
51 | #define STAGE3_AMBIENT 0x15D | ||
52 | #define STAGE4_AMBIENT 0x181 | ||
53 | #define STAGE5_AMBIENT 0x1A5 | ||
54 | #define STAGE6_AMBIENT 0x1C9 | ||
55 | #define STAGE7_AMBIENT 0x1ED | ||
56 | #define STAGE8_AMBIENT 0x211 | ||
57 | #define STAGE9_AMBIENT 0x234 | ||
58 | #define STAGE10_AMBIENT 0x259 | ||
59 | #define STAGE11_AMBIENT 0x27D | ||
60 | |||
61 | #define PER_STAGE_REG_NUM 36 | ||
62 | #define STAGE_NUM 12 | ||
63 | #define STAGE_CFGREG_NUM 8 | ||
64 | #define SYS_CFGREG_NUM 8 | ||
65 | |||
66 | /* | ||
67 | * driver information which will be used to maintain the software flow | ||
68 | */ | ||
69 | enum ad714x_device_state { IDLE, JITTER, ACTIVE, SPACE }; | ||
70 | |||
71 | struct ad714x_slider_drv { | ||
72 | int highest_stage; | ||
73 | int abs_pos; | ||
74 | int flt_pos; | ||
75 | enum ad714x_device_state state; | ||
76 | struct input_dev *input; | ||
77 | }; | ||
78 | |||
79 | struct ad714x_wheel_drv { | ||
80 | int abs_pos; | ||
81 | int flt_pos; | ||
82 | int pre_mean_value; | ||
83 | int pre_highest_stage; | ||
84 | int pre_mean_value_no_offset; | ||
85 | int mean_value; | ||
86 | int mean_value_no_offset; | ||
87 | int pos_offset; | ||
88 | int pos_ratio; | ||
89 | int highest_stage; | ||
90 | enum ad714x_device_state state; | ||
91 | struct input_dev *input; | ||
92 | }; | ||
93 | |||
94 | struct ad714x_touchpad_drv { | ||
95 | int x_highest_stage; | ||
96 | int x_flt_pos; | ||
97 | int x_abs_pos; | ||
98 | int y_highest_stage; | ||
99 | int y_flt_pos; | ||
100 | int y_abs_pos; | ||
101 | int left_ep; | ||
102 | int left_ep_val; | ||
103 | int right_ep; | ||
104 | int right_ep_val; | ||
105 | int top_ep; | ||
106 | int top_ep_val; | ||
107 | int bottom_ep; | ||
108 | int bottom_ep_val; | ||
109 | enum ad714x_device_state state; | ||
110 | struct input_dev *input; | ||
111 | }; | ||
112 | |||
113 | struct ad714x_button_drv { | ||
114 | enum ad714x_device_state state; | ||
115 | /* | ||
116 | * Unlike slider/wheel/touchpad, all buttons point to | ||
117 | * same input_dev instance | ||
118 | */ | ||
119 | struct input_dev *input; | ||
120 | }; | ||
121 | |||
122 | struct ad714x_driver_data { | ||
123 | struct ad714x_slider_drv *slider; | ||
124 | struct ad714x_wheel_drv *wheel; | ||
125 | struct ad714x_touchpad_drv *touchpad; | ||
126 | struct ad714x_button_drv *button; | ||
127 | }; | ||
128 | |||
129 | /* | ||
130 | * information to integrate all things which will be private data | ||
131 | * of spi/i2c device | ||
132 | */ | ||
133 | struct ad714x_chip { | ||
134 | unsigned short h_state; | ||
135 | unsigned short l_state; | ||
136 | unsigned short c_state; | ||
137 | unsigned short adc_reg[STAGE_NUM]; | ||
138 | unsigned short amb_reg[STAGE_NUM]; | ||
139 | unsigned short sensor_val[STAGE_NUM]; | ||
140 | |||
141 | struct ad714x_platform_data *hw; | ||
142 | struct ad714x_driver_data *sw; | ||
143 | |||
144 | int irq; | ||
145 | struct device *dev; | ||
146 | ad714x_read_t read; | ||
147 | ad714x_write_t write; | ||
148 | |||
149 | struct mutex mutex; | ||
150 | |||
151 | unsigned product; | ||
152 | unsigned version; | ||
153 | }; | ||
154 | |||
155 | static void ad714x_use_com_int(struct ad714x_chip *ad714x, | ||
156 | int start_stage, int end_stage) | ||
157 | { | ||
158 | unsigned short data; | ||
159 | unsigned short mask; | ||
160 | |||
161 | mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage); | ||
162 | |||
163 | ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); | ||
164 | data |= 1 << start_stage; | ||
165 | ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); | ||
166 | |||
167 | ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); | ||
168 | data &= ~mask; | ||
169 | ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); | ||
170 | } | ||
171 | |||
172 | static void ad714x_use_thr_int(struct ad714x_chip *ad714x, | ||
173 | int start_stage, int end_stage) | ||
174 | { | ||
175 | unsigned short data; | ||
176 | unsigned short mask; | ||
177 | |||
178 | mask = ((1 << (end_stage + 1)) - 1) - (1 << start_stage); | ||
179 | |||
180 | ad714x->read(ad714x->dev, STG_COM_INT_EN_REG, &data); | ||
181 | data &= ~(1 << start_stage); | ||
182 | ad714x->write(ad714x->dev, STG_COM_INT_EN_REG, data); | ||
183 | |||
184 | ad714x->read(ad714x->dev, STG_HIGH_INT_EN_REG, &data); | ||
185 | data |= mask; | ||
186 | ad714x->write(ad714x->dev, STG_HIGH_INT_EN_REG, data); | ||
187 | } | ||
188 | |||
189 | static int ad714x_cal_highest_stage(struct ad714x_chip *ad714x, | ||
190 | int start_stage, int end_stage) | ||
191 | { | ||
192 | int max_res = 0; | ||
193 | int max_idx = 0; | ||
194 | int i; | ||
195 | |||
196 | for (i = start_stage; i <= end_stage; i++) { | ||
197 | if (ad714x->sensor_val[i] > max_res) { | ||
198 | max_res = ad714x->sensor_val[i]; | ||
199 | max_idx = i; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | return max_idx; | ||
204 | } | ||
205 | |||
206 | static int ad714x_cal_abs_pos(struct ad714x_chip *ad714x, | ||
207 | int start_stage, int end_stage, | ||
208 | int highest_stage, int max_coord) | ||
209 | { | ||
210 | int a_param, b_param; | ||
211 | |||
212 | if (highest_stage == start_stage) { | ||
213 | a_param = ad714x->sensor_val[start_stage + 1]; | ||
214 | b_param = ad714x->sensor_val[start_stage] + | ||
215 | ad714x->sensor_val[start_stage + 1]; | ||
216 | } else if (highest_stage == end_stage) { | ||
217 | a_param = ad714x->sensor_val[end_stage] * | ||
218 | (end_stage - start_stage) + | ||
219 | ad714x->sensor_val[end_stage - 1] * | ||
220 | (end_stage - start_stage - 1); | ||
221 | b_param = ad714x->sensor_val[end_stage] + | ||
222 | ad714x->sensor_val[end_stage - 1]; | ||
223 | } else { | ||
224 | a_param = ad714x->sensor_val[highest_stage] * | ||
225 | (highest_stage - start_stage) + | ||
226 | ad714x->sensor_val[highest_stage - 1] * | ||
227 | (highest_stage - start_stage - 1) + | ||
228 | ad714x->sensor_val[highest_stage + 1] * | ||
229 | (highest_stage - start_stage + 1); | ||
230 | b_param = ad714x->sensor_val[highest_stage] + | ||
231 | ad714x->sensor_val[highest_stage - 1] + | ||
232 | ad714x->sensor_val[highest_stage + 1]; | ||
233 | } | ||
234 | |||
235 | return (max_coord / (end_stage - start_stage)) * a_param / b_param; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * One button can connect to multi positive and negative of CDCs | ||
240 | * Multi-buttons can connect to same positive/negative of one CDC | ||
241 | */ | ||
242 | static void ad714x_button_state_machine(struct ad714x_chip *ad714x, int idx) | ||
243 | { | ||
244 | struct ad714x_button_plat *hw = &ad714x->hw->button[idx]; | ||
245 | struct ad714x_button_drv *sw = &ad714x->sw->button[idx]; | ||
246 | |||
247 | switch (sw->state) { | ||
248 | case IDLE: | ||
249 | if (((ad714x->h_state & hw->h_mask) == hw->h_mask) && | ||
250 | ((ad714x->l_state & hw->l_mask) == hw->l_mask)) { | ||
251 | dev_dbg(ad714x->dev, "button %d touched\n", idx); | ||
252 | input_report_key(sw->input, hw->keycode, 1); | ||
253 | input_sync(sw->input); | ||
254 | sw->state = ACTIVE; | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | case ACTIVE: | ||
259 | if (((ad714x->h_state & hw->h_mask) != hw->h_mask) || | ||
260 | ((ad714x->l_state & hw->l_mask) != hw->l_mask)) { | ||
261 | dev_dbg(ad714x->dev, "button %d released\n", idx); | ||
262 | input_report_key(sw->input, hw->keycode, 0); | ||
263 | input_sync(sw->input); | ||
264 | sw->state = IDLE; | ||
265 | } | ||
266 | break; | ||
267 | |||
268 | default: | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * The response of a sensor is defined by the absolute number of codes | ||
275 | * between the current CDC value and the ambient value. | ||
276 | */ | ||
277 | static void ad714x_slider_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | ||
278 | { | ||
279 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
280 | int i; | ||
281 | |||
282 | for (i = hw->start_stage; i <= hw->end_stage; i++) { | ||
283 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | ||
284 | &ad714x->adc_reg[i]); | ||
285 | ad714x->read(ad714x->dev, | ||
286 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | ||
287 | &ad714x->amb_reg[i]); | ||
288 | |||
289 | ad714x->sensor_val[i] = abs(ad714x->adc_reg[i] - | ||
290 | ad714x->amb_reg[i]); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | static void ad714x_slider_cal_highest_stage(struct ad714x_chip *ad714x, int idx) | ||
295 | { | ||
296 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
297 | struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; | ||
298 | |||
299 | sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage, | ||
300 | hw->end_stage); | ||
301 | |||
302 | dev_dbg(ad714x->dev, "slider %d highest_stage:%d\n", idx, | ||
303 | sw->highest_stage); | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * The formulae are very straight forward. It uses the sensor with the | ||
308 | * highest response and the 2 adjacent ones. | ||
309 | * When Sensor 0 has the highest response, only sensor 0 and sensor 1 | ||
310 | * are used in the calculations. Similarly when the last sensor has the | ||
311 | * highest response, only the last sensor and the second last sensors | ||
312 | * are used in the calculations. | ||
313 | * | ||
314 | * For i= idx_of_peak_Sensor-1 to i= idx_of_peak_Sensor+1 | ||
315 | * v += Sensor response(i)*i | ||
316 | * w += Sensor response(i) | ||
317 | * POS=(Number_of_Positions_Wanted/(Number_of_Sensors_Used-1)) *(v/w) | ||
318 | */ | ||
319 | static void ad714x_slider_cal_abs_pos(struct ad714x_chip *ad714x, int idx) | ||
320 | { | ||
321 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
322 | struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; | ||
323 | |||
324 | sw->abs_pos = ad714x_cal_abs_pos(ad714x, hw->start_stage, hw->end_stage, | ||
325 | sw->highest_stage, hw->max_coord); | ||
326 | |||
327 | dev_dbg(ad714x->dev, "slider %d absolute position:%d\n", idx, | ||
328 | sw->abs_pos); | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * To minimise the Impact of the noise on the algorithm, ADI developed a | ||
333 | * routine that filters the CDC results after they have been read by the | ||
334 | * host processor. | ||
335 | * The filter used is an Infinite Input Response(IIR) filter implemented | ||
336 | * in firmware and attenuates the noise on the CDC results after they've | ||
337 | * been read by the host processor. | ||
338 | * Filtered_CDC_result = (Filtered_CDC_result * (10 - Coefficient) + | ||
339 | * Latest_CDC_result * Coefficient)/10 | ||
340 | */ | ||
341 | static void ad714x_slider_cal_flt_pos(struct ad714x_chip *ad714x, int idx) | ||
342 | { | ||
343 | struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; | ||
344 | |||
345 | sw->flt_pos = (sw->flt_pos * (10 - 4) + | ||
346 | sw->abs_pos * 4)/10; | ||
347 | |||
348 | dev_dbg(ad714x->dev, "slider %d filter position:%d\n", idx, | ||
349 | sw->flt_pos); | ||
350 | } | ||
351 | |||
352 | static void ad714x_slider_use_com_int(struct ad714x_chip *ad714x, int idx) | ||
353 | { | ||
354 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
355 | |||
356 | ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage); | ||
357 | } | ||
358 | |||
359 | static void ad714x_slider_use_thr_int(struct ad714x_chip *ad714x, int idx) | ||
360 | { | ||
361 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
362 | |||
363 | ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage); | ||
364 | } | ||
365 | |||
366 | static void ad714x_slider_state_machine(struct ad714x_chip *ad714x, int idx) | ||
367 | { | ||
368 | struct ad714x_slider_plat *hw = &ad714x->hw->slider[idx]; | ||
369 | struct ad714x_slider_drv *sw = &ad714x->sw->slider[idx]; | ||
370 | unsigned short h_state, c_state; | ||
371 | unsigned short mask; | ||
372 | |||
373 | mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1); | ||
374 | |||
375 | h_state = ad714x->h_state & mask; | ||
376 | c_state = ad714x->c_state & mask; | ||
377 | |||
378 | switch (sw->state) { | ||
379 | case IDLE: | ||
380 | if (h_state) { | ||
381 | sw->state = JITTER; | ||
382 | /* In End of Conversion interrupt mode, the AD714X | ||
383 | * continuously generates hardware interrupts. | ||
384 | */ | ||
385 | ad714x_slider_use_com_int(ad714x, idx); | ||
386 | dev_dbg(ad714x->dev, "slider %d touched\n", idx); | ||
387 | } | ||
388 | break; | ||
389 | |||
390 | case JITTER: | ||
391 | if (c_state == mask) { | ||
392 | ad714x_slider_cal_sensor_val(ad714x, idx); | ||
393 | ad714x_slider_cal_highest_stage(ad714x, idx); | ||
394 | ad714x_slider_cal_abs_pos(ad714x, idx); | ||
395 | sw->flt_pos = sw->abs_pos; | ||
396 | sw->state = ACTIVE; | ||
397 | } | ||
398 | break; | ||
399 | |||
400 | case ACTIVE: | ||
401 | if (c_state == mask) { | ||
402 | if (h_state) { | ||
403 | ad714x_slider_cal_sensor_val(ad714x, idx); | ||
404 | ad714x_slider_cal_highest_stage(ad714x, idx); | ||
405 | ad714x_slider_cal_abs_pos(ad714x, idx); | ||
406 | ad714x_slider_cal_flt_pos(ad714x, idx); | ||
407 | |||
408 | input_report_abs(sw->input, ABS_X, sw->flt_pos); | ||
409 | input_report_key(sw->input, BTN_TOUCH, 1); | ||
410 | } else { | ||
411 | /* When the user lifts off the sensor, configure | ||
412 | * the AD714X back to threshold interrupt mode. | ||
413 | */ | ||
414 | ad714x_slider_use_thr_int(ad714x, idx); | ||
415 | sw->state = IDLE; | ||
416 | input_report_key(sw->input, BTN_TOUCH, 0); | ||
417 | dev_dbg(ad714x->dev, "slider %d released\n", | ||
418 | idx); | ||
419 | } | ||
420 | input_sync(sw->input); | ||
421 | } | ||
422 | break; | ||
423 | |||
424 | default: | ||
425 | break; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * When the scroll wheel is activated, we compute the absolute position based | ||
431 | * on the sensor values. To calculate the position, we first determine the | ||
432 | * sensor that has the greatest response among the 8 sensors that constitutes | ||
433 | * the scrollwheel. Then we determined the 2 sensors on either sides of the | ||
434 | * sensor with the highest response and we apply weights to these sensors. | ||
435 | */ | ||
436 | static void ad714x_wheel_cal_highest_stage(struct ad714x_chip *ad714x, int idx) | ||
437 | { | ||
438 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
439 | struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; | ||
440 | |||
441 | sw->pre_highest_stage = sw->highest_stage; | ||
442 | sw->highest_stage = ad714x_cal_highest_stage(ad714x, hw->start_stage, | ||
443 | hw->end_stage); | ||
444 | |||
445 | dev_dbg(ad714x->dev, "wheel %d highest_stage:%d\n", idx, | ||
446 | sw->highest_stage); | ||
447 | } | ||
448 | |||
449 | static void ad714x_wheel_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | ||
450 | { | ||
451 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
452 | int i; | ||
453 | |||
454 | for (i = hw->start_stage; i <= hw->end_stage; i++) { | ||
455 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | ||
456 | &ad714x->adc_reg[i]); | ||
457 | ad714x->read(ad714x->dev, | ||
458 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | ||
459 | &ad714x->amb_reg[i]); | ||
460 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) | ||
461 | ad714x->sensor_val[i] = ad714x->adc_reg[i] - | ||
462 | ad714x->amb_reg[i]; | ||
463 | else | ||
464 | ad714x->sensor_val[i] = 0; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * When the scroll wheel is activated, we compute the absolute position based | ||
470 | * on the sensor values. To calculate the position, we first determine the | ||
471 | * sensor that has the greatest response among the 8 sensors that constitutes | ||
472 | * the scrollwheel. Then we determined the 2 sensors on either sides of the | ||
473 | * sensor with the highest response and we apply weights to these sensors. The | ||
474 | * result of this computation gives us the mean value which defined by the | ||
475 | * following formula: | ||
476 | * For i= second_before_highest_stage to i= second_after_highest_stage | ||
477 | * v += Sensor response(i)*WEIGHT*(i+3) | ||
478 | * w += Sensor response(i) | ||
479 | * Mean_Value=v/w | ||
480 | * pos_on_scrollwheel = (Mean_Value - position_offset) / position_ratio | ||
481 | */ | ||
482 | |||
483 | #define WEIGHT_FACTOR 30 | ||
484 | /* This constant prevents the "PositionOffset" from reaching a big value */ | ||
485 | #define OFFSET_POSITION_CLAMP 120 | ||
486 | static void ad714x_wheel_cal_abs_pos(struct ad714x_chip *ad714x, int idx) | ||
487 | { | ||
488 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
489 | struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; | ||
490 | int stage_num = hw->end_stage - hw->start_stage + 1; | ||
491 | int second_before, first_before, highest, first_after, second_after; | ||
492 | int a_param, b_param; | ||
493 | |||
494 | /* Calculate Mean value */ | ||
495 | |||
496 | second_before = (sw->highest_stage + stage_num - 2) % stage_num; | ||
497 | first_before = (sw->highest_stage + stage_num - 1) % stage_num; | ||
498 | highest = sw->highest_stage; | ||
499 | first_after = (sw->highest_stage + stage_num + 1) % stage_num; | ||
500 | second_after = (sw->highest_stage + stage_num + 2) % stage_num; | ||
501 | |||
502 | if (((sw->highest_stage - hw->start_stage) > 1) && | ||
503 | ((hw->end_stage - sw->highest_stage) > 1)) { | ||
504 | a_param = ad714x->sensor_val[second_before] * | ||
505 | (second_before - hw->start_stage + 3) + | ||
506 | ad714x->sensor_val[first_before] * | ||
507 | (second_before - hw->start_stage + 3) + | ||
508 | ad714x->sensor_val[highest] * | ||
509 | (second_before - hw->start_stage + 3) + | ||
510 | ad714x->sensor_val[first_after] * | ||
511 | (first_after - hw->start_stage + 3) + | ||
512 | ad714x->sensor_val[second_after] * | ||
513 | (second_after - hw->start_stage + 3); | ||
514 | } else { | ||
515 | a_param = ad714x->sensor_val[second_before] * | ||
516 | (second_before - hw->start_stage + 1) + | ||
517 | ad714x->sensor_val[first_before] * | ||
518 | (second_before - hw->start_stage + 2) + | ||
519 | ad714x->sensor_val[highest] * | ||
520 | (second_before - hw->start_stage + 3) + | ||
521 | ad714x->sensor_val[first_after] * | ||
522 | (first_after - hw->start_stage + 4) + | ||
523 | ad714x->sensor_val[second_after] * | ||
524 | (second_after - hw->start_stage + 5); | ||
525 | } | ||
526 | a_param *= WEIGHT_FACTOR; | ||
527 | |||
528 | b_param = ad714x->sensor_val[second_before] + | ||
529 | ad714x->sensor_val[first_before] + | ||
530 | ad714x->sensor_val[highest] + | ||
531 | ad714x->sensor_val[first_after] + | ||
532 | ad714x->sensor_val[second_after]; | ||
533 | |||
534 | sw->pre_mean_value = sw->mean_value; | ||
535 | sw->mean_value = a_param / b_param; | ||
536 | |||
537 | /* Calculate the offset */ | ||
538 | |||
539 | if ((sw->pre_highest_stage == hw->end_stage) && | ||
540 | (sw->highest_stage == hw->start_stage)) | ||
541 | sw->pos_offset = sw->mean_value; | ||
542 | else if ((sw->pre_highest_stage == hw->start_stage) && | ||
543 | (sw->highest_stage == hw->end_stage)) | ||
544 | sw->pos_offset = sw->pre_mean_value; | ||
545 | |||
546 | if (sw->pos_offset > OFFSET_POSITION_CLAMP) | ||
547 | sw->pos_offset = OFFSET_POSITION_CLAMP; | ||
548 | |||
549 | /* Calculate the mean value without the offset */ | ||
550 | |||
551 | sw->pre_mean_value_no_offset = sw->mean_value_no_offset; | ||
552 | sw->mean_value_no_offset = sw->mean_value - sw->pos_offset; | ||
553 | if (sw->mean_value_no_offset < 0) | ||
554 | sw->mean_value_no_offset = 0; | ||
555 | |||
556 | /* Calculate ratio to scale down to NUMBER_OF_WANTED_POSITIONS */ | ||
557 | |||
558 | if ((sw->pre_highest_stage == hw->end_stage) && | ||
559 | (sw->highest_stage == hw->start_stage)) | ||
560 | sw->pos_ratio = (sw->pre_mean_value_no_offset * 100) / | ||
561 | hw->max_coord; | ||
562 | else if ((sw->pre_highest_stage == hw->start_stage) && | ||
563 | (sw->highest_stage == hw->end_stage)) | ||
564 | sw->pos_ratio = (sw->mean_value_no_offset * 100) / | ||
565 | hw->max_coord; | ||
566 | sw->abs_pos = (sw->mean_value_no_offset * 100) / sw->pos_ratio; | ||
567 | if (sw->abs_pos > hw->max_coord) | ||
568 | sw->abs_pos = hw->max_coord; | ||
569 | } | ||
570 | |||
571 | static void ad714x_wheel_cal_flt_pos(struct ad714x_chip *ad714x, int idx) | ||
572 | { | ||
573 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
574 | struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; | ||
575 | if (((sw->pre_highest_stage == hw->end_stage) && | ||
576 | (sw->highest_stage == hw->start_stage)) || | ||
577 | ((sw->pre_highest_stage == hw->start_stage) && | ||
578 | (sw->highest_stage == hw->end_stage))) | ||
579 | sw->flt_pos = sw->abs_pos; | ||
580 | else | ||
581 | sw->flt_pos = ((sw->flt_pos * 30) + (sw->abs_pos * 71)) / 100; | ||
582 | |||
583 | if (sw->flt_pos > hw->max_coord) | ||
584 | sw->flt_pos = hw->max_coord; | ||
585 | } | ||
586 | |||
587 | static void ad714x_wheel_use_com_int(struct ad714x_chip *ad714x, int idx) | ||
588 | { | ||
589 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
590 | |||
591 | ad714x_use_com_int(ad714x, hw->start_stage, hw->end_stage); | ||
592 | } | ||
593 | |||
594 | static void ad714x_wheel_use_thr_int(struct ad714x_chip *ad714x, int idx) | ||
595 | { | ||
596 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
597 | |||
598 | ad714x_use_thr_int(ad714x, hw->start_stage, hw->end_stage); | ||
599 | } | ||
600 | |||
601 | static void ad714x_wheel_state_machine(struct ad714x_chip *ad714x, int idx) | ||
602 | { | ||
603 | struct ad714x_wheel_plat *hw = &ad714x->hw->wheel[idx]; | ||
604 | struct ad714x_wheel_drv *sw = &ad714x->sw->wheel[idx]; | ||
605 | unsigned short h_state, c_state; | ||
606 | unsigned short mask; | ||
607 | |||
608 | mask = ((1 << (hw->end_stage + 1)) - 1) - ((1 << hw->start_stage) - 1); | ||
609 | |||
610 | h_state = ad714x->h_state & mask; | ||
611 | c_state = ad714x->c_state & mask; | ||
612 | |||
613 | switch (sw->state) { | ||
614 | case IDLE: | ||
615 | if (h_state) { | ||
616 | sw->state = JITTER; | ||
617 | /* In End of Conversion interrupt mode, the AD714X | ||
618 | * continuously generates hardware interrupts. | ||
619 | */ | ||
620 | ad714x_wheel_use_com_int(ad714x, idx); | ||
621 | dev_dbg(ad714x->dev, "wheel %d touched\n", idx); | ||
622 | } | ||
623 | break; | ||
624 | |||
625 | case JITTER: | ||
626 | if (c_state == mask) { | ||
627 | ad714x_wheel_cal_sensor_val(ad714x, idx); | ||
628 | ad714x_wheel_cal_highest_stage(ad714x, idx); | ||
629 | ad714x_wheel_cal_abs_pos(ad714x, idx); | ||
630 | sw->flt_pos = sw->abs_pos; | ||
631 | sw->state = ACTIVE; | ||
632 | } | ||
633 | break; | ||
634 | |||
635 | case ACTIVE: | ||
636 | if (c_state == mask) { | ||
637 | if (h_state) { | ||
638 | ad714x_wheel_cal_sensor_val(ad714x, idx); | ||
639 | ad714x_wheel_cal_highest_stage(ad714x, idx); | ||
640 | ad714x_wheel_cal_abs_pos(ad714x, idx); | ||
641 | ad714x_wheel_cal_flt_pos(ad714x, idx); | ||
642 | |||
643 | input_report_abs(sw->input, ABS_WHEEL, | ||
644 | sw->abs_pos); | ||
645 | input_report_key(sw->input, BTN_TOUCH, 1); | ||
646 | } else { | ||
647 | /* When the user lifts off the sensor, configure | ||
648 | * the AD714X back to threshold interrupt mode. | ||
649 | */ | ||
650 | ad714x_wheel_use_thr_int(ad714x, idx); | ||
651 | sw->state = IDLE; | ||
652 | input_report_key(sw->input, BTN_TOUCH, 0); | ||
653 | |||
654 | dev_dbg(ad714x->dev, "wheel %d released\n", | ||
655 | idx); | ||
656 | } | ||
657 | input_sync(sw->input); | ||
658 | } | ||
659 | break; | ||
660 | |||
661 | default: | ||
662 | break; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | static void touchpad_cal_sensor_val(struct ad714x_chip *ad714x, int idx) | ||
667 | { | ||
668 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
669 | int i; | ||
670 | |||
671 | for (i = hw->x_start_stage; i <= hw->x_end_stage; i++) { | ||
672 | ad714x->read(ad714x->dev, CDC_RESULT_S0 + i, | ||
673 | &ad714x->adc_reg[i]); | ||
674 | ad714x->read(ad714x->dev, | ||
675 | STAGE0_AMBIENT + i * PER_STAGE_REG_NUM, | ||
676 | &ad714x->amb_reg[i]); | ||
677 | if (ad714x->adc_reg[i] > ad714x->amb_reg[i]) | ||
678 | ad714x->sensor_val[i] = ad714x->adc_reg[i] - | ||
679 | ad714x->amb_reg[i]; | ||
680 | else | ||
681 | ad714x->sensor_val[i] = 0; | ||
682 | } | ||
683 | } | ||
684 | |||
685 | static void touchpad_cal_highest_stage(struct ad714x_chip *ad714x, int idx) | ||
686 | { | ||
687 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
688 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
689 | |||
690 | sw->x_highest_stage = ad714x_cal_highest_stage(ad714x, | ||
691 | hw->x_start_stage, hw->x_end_stage); | ||
692 | sw->y_highest_stage = ad714x_cal_highest_stage(ad714x, | ||
693 | hw->y_start_stage, hw->y_end_stage); | ||
694 | |||
695 | dev_dbg(ad714x->dev, | ||
696 | "touchpad %d x_highest_stage:%d, y_highest_stage:%d\n", | ||
697 | idx, sw->x_highest_stage, sw->y_highest_stage); | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * If 2 fingers are touching the sensor then 2 peaks can be observed in the | ||
702 | * distribution. | ||
703 | * The arithmetic doesn't support to get absolute coordinates for multi-touch | ||
704 | * yet. | ||
705 | */ | ||
706 | static int touchpad_check_second_peak(struct ad714x_chip *ad714x, int idx) | ||
707 | { | ||
708 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
709 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
710 | int i; | ||
711 | |||
712 | for (i = hw->x_start_stage; i < sw->x_highest_stage; i++) { | ||
713 | if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1]) | ||
714 | > (ad714x->sensor_val[i + 1] / 10)) | ||
715 | return 1; | ||
716 | } | ||
717 | |||
718 | for (i = sw->x_highest_stage; i < hw->x_end_stage; i++) { | ||
719 | if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i]) | ||
720 | > (ad714x->sensor_val[i] / 10)) | ||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | for (i = hw->y_start_stage; i < sw->y_highest_stage; i++) { | ||
725 | if ((ad714x->sensor_val[i] - ad714x->sensor_val[i + 1]) | ||
726 | > (ad714x->sensor_val[i + 1] / 10)) | ||
727 | return 1; | ||
728 | } | ||
729 | |||
730 | for (i = sw->y_highest_stage; i < hw->y_end_stage; i++) { | ||
731 | if ((ad714x->sensor_val[i + 1] - ad714x->sensor_val[i]) | ||
732 | > (ad714x->sensor_val[i] / 10)) | ||
733 | return 1; | ||
734 | } | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | /* | ||
740 | * If only one finger is used to activate the touch pad then only 1 peak will be | ||
741 | * registered in the distribution. This peak and the 2 adjacent sensors will be | ||
742 | * used in the calculation of the absolute position. This will prevent hand | ||
743 | * shadows to affect the absolute position calculation. | ||
744 | */ | ||
745 | static void touchpad_cal_abs_pos(struct ad714x_chip *ad714x, int idx) | ||
746 | { | ||
747 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
748 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
749 | |||
750 | sw->x_abs_pos = ad714x_cal_abs_pos(ad714x, hw->x_start_stage, | ||
751 | hw->x_end_stage, sw->x_highest_stage, hw->x_max_coord); | ||
752 | sw->y_abs_pos = ad714x_cal_abs_pos(ad714x, hw->y_start_stage, | ||
753 | hw->y_end_stage, sw->y_highest_stage, hw->y_max_coord); | ||
754 | |||
755 | dev_dbg(ad714x->dev, "touchpad %d absolute position:(%d, %d)\n", idx, | ||
756 | sw->x_abs_pos, sw->y_abs_pos); | ||
757 | } | ||
758 | |||
759 | static void touchpad_cal_flt_pos(struct ad714x_chip *ad714x, int idx) | ||
760 | { | ||
761 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
762 | |||
763 | sw->x_flt_pos = (sw->x_flt_pos * (10 - 4) + | ||
764 | sw->x_abs_pos * 4)/10; | ||
765 | sw->y_flt_pos = (sw->y_flt_pos * (10 - 4) + | ||
766 | sw->y_abs_pos * 4)/10; | ||
767 | |||
768 | dev_dbg(ad714x->dev, "touchpad %d filter position:(%d, %d)\n", | ||
769 | idx, sw->x_flt_pos, sw->y_flt_pos); | ||
770 | } | ||
771 | |||
772 | /* | ||
773 | * To prevent distortion from showing in the absolute position, it is | ||
774 | * necessary to detect the end points. When endpoints are detected, the | ||
775 | * driver stops updating the status variables with absolute positions. | ||
776 | * End points are detected on the 4 edges of the touchpad sensor. The | ||
777 | * method to detect them is the same for all 4. | ||
778 | * To detect the end points, the firmware computes the difference in | ||
779 | * percent between the sensor on the edge and the adjacent one. The | ||
780 | * difference is calculated in percent in order to make the end point | ||
781 | * detection independent of the pressure. | ||
782 | */ | ||
783 | |||
784 | #define LEFT_END_POINT_DETECTION_LEVEL 550 | ||
785 | #define RIGHT_END_POINT_DETECTION_LEVEL 750 | ||
786 | #define LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL 850 | ||
787 | #define TOP_END_POINT_DETECTION_LEVEL 550 | ||
788 | #define BOTTOM_END_POINT_DETECTION_LEVEL 950 | ||
789 | #define TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL 700 | ||
790 | static int touchpad_check_endpoint(struct ad714x_chip *ad714x, int idx) | ||
791 | { | ||
792 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
793 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
794 | int percent_sensor_diff; | ||
795 | |||
796 | /* left endpoint detect */ | ||
797 | percent_sensor_diff = (ad714x->sensor_val[hw->x_start_stage] - | ||
798 | ad714x->sensor_val[hw->x_start_stage + 1]) * 100 / | ||
799 | ad714x->sensor_val[hw->x_start_stage + 1]; | ||
800 | if (!sw->left_ep) { | ||
801 | if (percent_sensor_diff >= LEFT_END_POINT_DETECTION_LEVEL) { | ||
802 | sw->left_ep = 1; | ||
803 | sw->left_ep_val = | ||
804 | ad714x->sensor_val[hw->x_start_stage + 1]; | ||
805 | } | ||
806 | } else { | ||
807 | if ((percent_sensor_diff < LEFT_END_POINT_DETECTION_LEVEL) && | ||
808 | (ad714x->sensor_val[hw->x_start_stage + 1] > | ||
809 | LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->left_ep_val)) | ||
810 | sw->left_ep = 0; | ||
811 | } | ||
812 | |||
813 | /* right endpoint detect */ | ||
814 | percent_sensor_diff = (ad714x->sensor_val[hw->x_end_stage] - | ||
815 | ad714x->sensor_val[hw->x_end_stage - 1]) * 100 / | ||
816 | ad714x->sensor_val[hw->x_end_stage - 1]; | ||
817 | if (!sw->right_ep) { | ||
818 | if (percent_sensor_diff >= RIGHT_END_POINT_DETECTION_LEVEL) { | ||
819 | sw->right_ep = 1; | ||
820 | sw->right_ep_val = | ||
821 | ad714x->sensor_val[hw->x_end_stage - 1]; | ||
822 | } | ||
823 | } else { | ||
824 | if ((percent_sensor_diff < RIGHT_END_POINT_DETECTION_LEVEL) && | ||
825 | (ad714x->sensor_val[hw->x_end_stage - 1] > | ||
826 | LEFT_RIGHT_END_POINT_DEAVTIVALION_LEVEL + sw->right_ep_val)) | ||
827 | sw->right_ep = 0; | ||
828 | } | ||
829 | |||
830 | /* top endpoint detect */ | ||
831 | percent_sensor_diff = (ad714x->sensor_val[hw->y_start_stage] - | ||
832 | ad714x->sensor_val[hw->y_start_stage + 1]) * 100 / | ||
833 | ad714x->sensor_val[hw->y_start_stage + 1]; | ||
834 | if (!sw->top_ep) { | ||
835 | if (percent_sensor_diff >= TOP_END_POINT_DETECTION_LEVEL) { | ||
836 | sw->top_ep = 1; | ||
837 | sw->top_ep_val = | ||
838 | ad714x->sensor_val[hw->y_start_stage + 1]; | ||
839 | } | ||
840 | } else { | ||
841 | if ((percent_sensor_diff < TOP_END_POINT_DETECTION_LEVEL) && | ||
842 | (ad714x->sensor_val[hw->y_start_stage + 1] > | ||
843 | TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->top_ep_val)) | ||
844 | sw->top_ep = 0; | ||
845 | } | ||
846 | |||
847 | /* bottom endpoint detect */ | ||
848 | percent_sensor_diff = (ad714x->sensor_val[hw->y_end_stage] - | ||
849 | ad714x->sensor_val[hw->y_end_stage - 1]) * 100 / | ||
850 | ad714x->sensor_val[hw->y_end_stage - 1]; | ||
851 | if (!sw->bottom_ep) { | ||
852 | if (percent_sensor_diff >= BOTTOM_END_POINT_DETECTION_LEVEL) { | ||
853 | sw->bottom_ep = 1; | ||
854 | sw->bottom_ep_val = | ||
855 | ad714x->sensor_val[hw->y_end_stage - 1]; | ||
856 | } | ||
857 | } else { | ||
858 | if ((percent_sensor_diff < BOTTOM_END_POINT_DETECTION_LEVEL) && | ||
859 | (ad714x->sensor_val[hw->y_end_stage - 1] > | ||
860 | TOP_BOTTOM_END_POINT_DEAVTIVALION_LEVEL + sw->bottom_ep_val)) | ||
861 | sw->bottom_ep = 0; | ||
862 | } | ||
863 | |||
864 | return sw->left_ep || sw->right_ep || sw->top_ep || sw->bottom_ep; | ||
865 | } | ||
866 | |||
867 | static void touchpad_use_com_int(struct ad714x_chip *ad714x, int idx) | ||
868 | { | ||
869 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
870 | |||
871 | ad714x_use_com_int(ad714x, hw->x_start_stage, hw->x_end_stage); | ||
872 | } | ||
873 | |||
874 | static void touchpad_use_thr_int(struct ad714x_chip *ad714x, int idx) | ||
875 | { | ||
876 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
877 | |||
878 | ad714x_use_thr_int(ad714x, hw->x_start_stage, hw->x_end_stage); | ||
879 | ad714x_use_thr_int(ad714x, hw->y_start_stage, hw->y_end_stage); | ||
880 | } | ||
881 | |||
882 | static void ad714x_touchpad_state_machine(struct ad714x_chip *ad714x, int idx) | ||
883 | { | ||
884 | struct ad714x_touchpad_plat *hw = &ad714x->hw->touchpad[idx]; | ||
885 | struct ad714x_touchpad_drv *sw = &ad714x->sw->touchpad[idx]; | ||
886 | unsigned short h_state, c_state; | ||
887 | unsigned short mask; | ||
888 | |||
889 | mask = (((1 << (hw->x_end_stage + 1)) - 1) - | ||
890 | ((1 << hw->x_start_stage) - 1)) + | ||
891 | (((1 << (hw->y_end_stage + 1)) - 1) - | ||
892 | ((1 << hw->y_start_stage) - 1)); | ||
893 | |||
894 | h_state = ad714x->h_state & mask; | ||
895 | c_state = ad714x->c_state & mask; | ||
896 | |||
897 | switch (sw->state) { | ||
898 | case IDLE: | ||
899 | if (h_state) { | ||
900 | sw->state = JITTER; | ||
901 | /* In End of Conversion interrupt mode, the AD714X | ||
902 | * continuously generates hardware interrupts. | ||
903 | */ | ||
904 | touchpad_use_com_int(ad714x, idx); | ||
905 | dev_dbg(ad714x->dev, "touchpad %d touched\n", idx); | ||
906 | } | ||
907 | break; | ||
908 | |||
909 | case JITTER: | ||
910 | if (c_state == mask) { | ||
911 | touchpad_cal_sensor_val(ad714x, idx); | ||
912 | touchpad_cal_highest_stage(ad714x, idx); | ||
913 | if ((!touchpad_check_second_peak(ad714x, idx)) && | ||
914 | (!touchpad_check_endpoint(ad714x, idx))) { | ||
915 | dev_dbg(ad714x->dev, | ||
916 | "touchpad%d, 2 fingers or endpoint\n", | ||
917 | idx); | ||
918 | touchpad_cal_abs_pos(ad714x, idx); | ||
919 | sw->x_flt_pos = sw->x_abs_pos; | ||
920 | sw->y_flt_pos = sw->y_abs_pos; | ||
921 | sw->state = ACTIVE; | ||
922 | } | ||
923 | } | ||
924 | break; | ||
925 | |||
926 | case ACTIVE: | ||
927 | if (c_state == mask) { | ||
928 | if (h_state) { | ||
929 | touchpad_cal_sensor_val(ad714x, idx); | ||
930 | touchpad_cal_highest_stage(ad714x, idx); | ||
931 | if ((!touchpad_check_second_peak(ad714x, idx)) | ||
932 | && (!touchpad_check_endpoint(ad714x, idx))) { | ||
933 | touchpad_cal_abs_pos(ad714x, idx); | ||
934 | touchpad_cal_flt_pos(ad714x, idx); | ||
935 | input_report_abs(sw->input, ABS_X, | ||
936 | sw->x_flt_pos); | ||
937 | input_report_abs(sw->input, ABS_Y, | ||
938 | sw->y_flt_pos); | ||
939 | input_report_key(sw->input, BTN_TOUCH, | ||
940 | 1); | ||
941 | } | ||
942 | } else { | ||
943 | /* When the user lifts off the sensor, configure | ||
944 | * the AD714X back to threshold interrupt mode. | ||
945 | */ | ||
946 | touchpad_use_thr_int(ad714x, idx); | ||
947 | sw->state = IDLE; | ||
948 | input_report_key(sw->input, BTN_TOUCH, 0); | ||
949 | dev_dbg(ad714x->dev, "touchpad %d released\n", | ||
950 | idx); | ||
951 | } | ||
952 | input_sync(sw->input); | ||
953 | } | ||
954 | break; | ||
955 | |||
956 | default: | ||
957 | break; | ||
958 | } | ||
959 | } | ||
960 | |||
961 | static int ad714x_hw_detect(struct ad714x_chip *ad714x) | ||
962 | { | ||
963 | unsigned short data; | ||
964 | |||
965 | ad714x->read(ad714x->dev, AD714X_PARTID_REG, &data); | ||
966 | switch (data & 0xFFF0) { | ||
967 | case AD7142_PARTID: | ||
968 | ad714x->product = 0x7142; | ||
969 | ad714x->version = data & 0xF; | ||
970 | dev_info(ad714x->dev, "found AD7142 captouch, rev:%d\n", | ||
971 | ad714x->version); | ||
972 | return 0; | ||
973 | |||
974 | case AD7143_PARTID: | ||
975 | ad714x->product = 0x7143; | ||
976 | ad714x->version = data & 0xF; | ||
977 | dev_info(ad714x->dev, "found AD7143 captouch, rev:%d\n", | ||
978 | ad714x->version); | ||
979 | return 0; | ||
980 | |||
981 | case AD7147_PARTID: | ||
982 | ad714x->product = 0x7147; | ||
983 | ad714x->version = data & 0xF; | ||
984 | dev_info(ad714x->dev, "found AD7147(A) captouch, rev:%d\n", | ||
985 | ad714x->version); | ||
986 | return 0; | ||
987 | |||
988 | case AD7148_PARTID: | ||
989 | ad714x->product = 0x7148; | ||
990 | ad714x->version = data & 0xF; | ||
991 | dev_info(ad714x->dev, "found AD7148 captouch, rev:%d\n", | ||
992 | ad714x->version); | ||
993 | return 0; | ||
994 | |||
995 | default: | ||
996 | dev_err(ad714x->dev, | ||
997 | "fail to detect AD714X captouch, read ID is %04x\n", | ||
998 | data); | ||
999 | return -ENODEV; | ||
1000 | } | ||
1001 | } | ||
1002 | |||
1003 | static void ad714x_hw_init(struct ad714x_chip *ad714x) | ||
1004 | { | ||
1005 | int i, j; | ||
1006 | unsigned short reg_base; | ||
1007 | unsigned short data; | ||
1008 | |||
1009 | /* configuration CDC and interrupts */ | ||
1010 | |||
1011 | for (i = 0; i < STAGE_NUM; i++) { | ||
1012 | reg_base = AD714X_STAGECFG_REG + i * STAGE_CFGREG_NUM; | ||
1013 | for (j = 0; j < STAGE_CFGREG_NUM; j++) | ||
1014 | ad714x->write(ad714x->dev, reg_base + j, | ||
1015 | ad714x->hw->stage_cfg_reg[i][j]); | ||
1016 | } | ||
1017 | |||
1018 | for (i = 0; i < SYS_CFGREG_NUM; i++) | ||
1019 | ad714x->write(ad714x->dev, AD714X_SYSCFG_REG + i, | ||
1020 | ad714x->hw->sys_cfg_reg[i]); | ||
1021 | for (i = 0; i < SYS_CFGREG_NUM; i++) | ||
1022 | ad714x->read(ad714x->dev, AD714X_SYSCFG_REG + i, | ||
1023 | &data); | ||
1024 | |||
1025 | ad714x->write(ad714x->dev, AD714X_STG_CAL_EN_REG, 0xFFF); | ||
1026 | |||
1027 | /* clear all interrupts */ | ||
1028 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); | ||
1029 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); | ||
1030 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); | ||
1031 | } | ||
1032 | |||
1033 | static irqreturn_t ad714x_interrupt_thread(int irq, void *data) | ||
1034 | { | ||
1035 | struct ad714x_chip *ad714x = data; | ||
1036 | int i; | ||
1037 | |||
1038 | mutex_lock(&ad714x->mutex); | ||
1039 | |||
1040 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &ad714x->l_state); | ||
1041 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &ad714x->h_state); | ||
1042 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &ad714x->c_state); | ||
1043 | |||
1044 | for (i = 0; i < ad714x->hw->button_num; i++) | ||
1045 | ad714x_button_state_machine(ad714x, i); | ||
1046 | for (i = 0; i < ad714x->hw->slider_num; i++) | ||
1047 | ad714x_slider_state_machine(ad714x, i); | ||
1048 | for (i = 0; i < ad714x->hw->wheel_num; i++) | ||
1049 | ad714x_wheel_state_machine(ad714x, i); | ||
1050 | for (i = 0; i < ad714x->hw->touchpad_num; i++) | ||
1051 | ad714x_touchpad_state_machine(ad714x, i); | ||
1052 | |||
1053 | mutex_unlock(&ad714x->mutex); | ||
1054 | |||
1055 | return IRQ_HANDLED; | ||
1056 | } | ||
1057 | |||
1058 | #define MAX_DEVICE_NUM 8 | ||
1059 | struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, | ||
1060 | ad714x_read_t read, ad714x_write_t write) | ||
1061 | { | ||
1062 | int i, alloc_idx; | ||
1063 | int error; | ||
1064 | struct input_dev *input[MAX_DEVICE_NUM]; | ||
1065 | |||
1066 | struct ad714x_platform_data *plat_data = dev->platform_data; | ||
1067 | struct ad714x_chip *ad714x; | ||
1068 | void *drv_mem; | ||
1069 | |||
1070 | struct ad714x_button_drv *bt_drv; | ||
1071 | struct ad714x_slider_drv *sd_drv; | ||
1072 | struct ad714x_wheel_drv *wl_drv; | ||
1073 | struct ad714x_touchpad_drv *tp_drv; | ||
1074 | |||
1075 | |||
1076 | if (irq <= 0) { | ||
1077 | dev_err(dev, "IRQ not configured!\n"); | ||
1078 | error = -EINVAL; | ||
1079 | goto err_out; | ||
1080 | } | ||
1081 | |||
1082 | if (dev->platform_data == NULL) { | ||
1083 | dev_err(dev, "platform data for ad714x doesn't exist\n"); | ||
1084 | error = -EINVAL; | ||
1085 | goto err_out; | ||
1086 | } | ||
1087 | |||
1088 | ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) + | ||
1089 | sizeof(*sd_drv) * plat_data->slider_num + | ||
1090 | sizeof(*wl_drv) * plat_data->wheel_num + | ||
1091 | sizeof(*tp_drv) * plat_data->touchpad_num + | ||
1092 | sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL); | ||
1093 | if (!ad714x) { | ||
1094 | error = -ENOMEM; | ||
1095 | goto err_out; | ||
1096 | } | ||
1097 | |||
1098 | ad714x->hw = plat_data; | ||
1099 | |||
1100 | drv_mem = ad714x + 1; | ||
1101 | ad714x->sw = drv_mem; | ||
1102 | drv_mem += sizeof(*ad714x->sw); | ||
1103 | ad714x->sw->slider = sd_drv = drv_mem; | ||
1104 | drv_mem += sizeof(*sd_drv) * ad714x->hw->slider_num; | ||
1105 | ad714x->sw->wheel = wl_drv = drv_mem; | ||
1106 | drv_mem += sizeof(*wl_drv) * ad714x->hw->wheel_num; | ||
1107 | ad714x->sw->touchpad = tp_drv = drv_mem; | ||
1108 | drv_mem += sizeof(*tp_drv) * ad714x->hw->touchpad_num; | ||
1109 | ad714x->sw->button = bt_drv = drv_mem; | ||
1110 | drv_mem += sizeof(*bt_drv) * ad714x->hw->button_num; | ||
1111 | |||
1112 | ad714x->read = read; | ||
1113 | ad714x->write = write; | ||
1114 | ad714x->irq = irq; | ||
1115 | ad714x->dev = dev; | ||
1116 | |||
1117 | error = ad714x_hw_detect(ad714x); | ||
1118 | if (error) | ||
1119 | goto err_free_mem; | ||
1120 | |||
1121 | /* initilize and request sw/hw resources */ | ||
1122 | |||
1123 | ad714x_hw_init(ad714x); | ||
1124 | mutex_init(&ad714x->mutex); | ||
1125 | |||
1126 | /* | ||
1127 | * Allocate and register AD714X input device | ||
1128 | */ | ||
1129 | alloc_idx = 0; | ||
1130 | |||
1131 | /* a slider uses one input_dev instance */ | ||
1132 | if (ad714x->hw->slider_num > 0) { | ||
1133 | struct ad714x_slider_plat *sd_plat = ad714x->hw->slider; | ||
1134 | |||
1135 | for (i = 0; i < ad714x->hw->slider_num; i++) { | ||
1136 | sd_drv[i].input = input[alloc_idx] = input_allocate_device(); | ||
1137 | if (!input[alloc_idx]) { | ||
1138 | error = -ENOMEM; | ||
1139 | goto err_free_dev; | ||
1140 | } | ||
1141 | |||
1142 | __set_bit(EV_ABS, input[alloc_idx]->evbit); | ||
1143 | __set_bit(EV_KEY, input[alloc_idx]->evbit); | ||
1144 | __set_bit(ABS_X, input[alloc_idx]->absbit); | ||
1145 | __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); | ||
1146 | input_set_abs_params(input[alloc_idx], | ||
1147 | ABS_X, 0, sd_plat->max_coord, 0, 0); | ||
1148 | |||
1149 | input[alloc_idx]->id.bustype = bus_type; | ||
1150 | input[alloc_idx]->id.product = ad714x->product; | ||
1151 | input[alloc_idx]->id.version = ad714x->version; | ||
1152 | |||
1153 | error = input_register_device(input[alloc_idx]); | ||
1154 | if (error) | ||
1155 | goto err_free_dev; | ||
1156 | |||
1157 | alloc_idx++; | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | /* a wheel uses one input_dev instance */ | ||
1162 | if (ad714x->hw->wheel_num > 0) { | ||
1163 | struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel; | ||
1164 | |||
1165 | for (i = 0; i < ad714x->hw->wheel_num; i++) { | ||
1166 | wl_drv[i].input = input[alloc_idx] = input_allocate_device(); | ||
1167 | if (!input[alloc_idx]) { | ||
1168 | error = -ENOMEM; | ||
1169 | goto err_free_dev; | ||
1170 | } | ||
1171 | |||
1172 | __set_bit(EV_KEY, input[alloc_idx]->evbit); | ||
1173 | __set_bit(EV_ABS, input[alloc_idx]->evbit); | ||
1174 | __set_bit(ABS_WHEEL, input[alloc_idx]->absbit); | ||
1175 | __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); | ||
1176 | input_set_abs_params(input[alloc_idx], | ||
1177 | ABS_WHEEL, 0, wl_plat->max_coord, 0, 0); | ||
1178 | |||
1179 | input[alloc_idx]->id.bustype = bus_type; | ||
1180 | input[alloc_idx]->id.product = ad714x->product; | ||
1181 | input[alloc_idx]->id.version = ad714x->version; | ||
1182 | |||
1183 | error = input_register_device(input[alloc_idx]); | ||
1184 | if (error) | ||
1185 | goto err_free_dev; | ||
1186 | |||
1187 | alloc_idx++; | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | /* a touchpad uses one input_dev instance */ | ||
1192 | if (ad714x->hw->touchpad_num > 0) { | ||
1193 | struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad; | ||
1194 | |||
1195 | for (i = 0; i < ad714x->hw->touchpad_num; i++) { | ||
1196 | tp_drv[i].input = input[alloc_idx] = input_allocate_device(); | ||
1197 | if (!input[alloc_idx]) { | ||
1198 | error = -ENOMEM; | ||
1199 | goto err_free_dev; | ||
1200 | } | ||
1201 | |||
1202 | __set_bit(EV_ABS, input[alloc_idx]->evbit); | ||
1203 | __set_bit(EV_KEY, input[alloc_idx]->evbit); | ||
1204 | __set_bit(ABS_X, input[alloc_idx]->absbit); | ||
1205 | __set_bit(ABS_Y, input[alloc_idx]->absbit); | ||
1206 | __set_bit(BTN_TOUCH, input[alloc_idx]->keybit); | ||
1207 | input_set_abs_params(input[alloc_idx], | ||
1208 | ABS_X, 0, tp_plat->x_max_coord, 0, 0); | ||
1209 | input_set_abs_params(input[alloc_idx], | ||
1210 | ABS_Y, 0, tp_plat->y_max_coord, 0, 0); | ||
1211 | |||
1212 | input[alloc_idx]->id.bustype = bus_type; | ||
1213 | input[alloc_idx]->id.product = ad714x->product; | ||
1214 | input[alloc_idx]->id.version = ad714x->version; | ||
1215 | |||
1216 | error = input_register_device(input[alloc_idx]); | ||
1217 | if (error) | ||
1218 | goto err_free_dev; | ||
1219 | |||
1220 | alloc_idx++; | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | /* all buttons use one input node */ | ||
1225 | if (ad714x->hw->button_num > 0) { | ||
1226 | struct ad714x_button_plat *bt_plat = ad714x->hw->button; | ||
1227 | |||
1228 | input[alloc_idx] = input_allocate_device(); | ||
1229 | if (!input[alloc_idx]) { | ||
1230 | error = -ENOMEM; | ||
1231 | goto err_free_dev; | ||
1232 | } | ||
1233 | |||
1234 | __set_bit(EV_KEY, input[alloc_idx]->evbit); | ||
1235 | for (i = 0; i < ad714x->hw->button_num; i++) { | ||
1236 | bt_drv[i].input = input[alloc_idx]; | ||
1237 | __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit); | ||
1238 | } | ||
1239 | |||
1240 | input[alloc_idx]->id.bustype = bus_type; | ||
1241 | input[alloc_idx]->id.product = ad714x->product; | ||
1242 | input[alloc_idx]->id.version = ad714x->version; | ||
1243 | |||
1244 | error = input_register_device(input[alloc_idx]); | ||
1245 | if (error) | ||
1246 | goto err_free_dev; | ||
1247 | |||
1248 | alloc_idx++; | ||
1249 | } | ||
1250 | |||
1251 | error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread, | ||
1252 | IRQF_TRIGGER_FALLING, "ad714x_captouch", ad714x); | ||
1253 | if (error) { | ||
1254 | dev_err(dev, "can't allocate irq %d\n", ad714x->irq); | ||
1255 | goto err_unreg_dev; | ||
1256 | } | ||
1257 | |||
1258 | return ad714x; | ||
1259 | |||
1260 | err_free_dev: | ||
1261 | dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx); | ||
1262 | input_free_device(input[alloc_idx]); | ||
1263 | err_unreg_dev: | ||
1264 | while (--alloc_idx >= 0) | ||
1265 | input_unregister_device(input[alloc_idx]); | ||
1266 | err_free_mem: | ||
1267 | kfree(ad714x); | ||
1268 | err_out: | ||
1269 | return ERR_PTR(error); | ||
1270 | } | ||
1271 | EXPORT_SYMBOL(ad714x_probe); | ||
1272 | |||
1273 | void ad714x_remove(struct ad714x_chip *ad714x) | ||
1274 | { | ||
1275 | struct ad714x_platform_data *hw = ad714x->hw; | ||
1276 | struct ad714x_driver_data *sw = ad714x->sw; | ||
1277 | int i; | ||
1278 | |||
1279 | free_irq(ad714x->irq, ad714x); | ||
1280 | |||
1281 | /* unregister and free all input devices */ | ||
1282 | |||
1283 | for (i = 0; i < hw->slider_num; i++) | ||
1284 | input_unregister_device(sw->slider[i].input); | ||
1285 | |||
1286 | for (i = 0; i < hw->wheel_num; i++) | ||
1287 | input_unregister_device(sw->wheel[i].input); | ||
1288 | |||
1289 | for (i = 0; i < hw->touchpad_num; i++) | ||
1290 | input_unregister_device(sw->touchpad[i].input); | ||
1291 | |||
1292 | if (hw->button_num) | ||
1293 | input_unregister_device(sw->button[0].input); | ||
1294 | |||
1295 | kfree(ad714x); | ||
1296 | } | ||
1297 | EXPORT_SYMBOL(ad714x_remove); | ||
1298 | |||
1299 | #ifdef CONFIG_PM | ||
1300 | int ad714x_disable(struct ad714x_chip *ad714x) | ||
1301 | { | ||
1302 | unsigned short data; | ||
1303 | |||
1304 | dev_dbg(ad714x->dev, "%s enter\n", __func__); | ||
1305 | |||
1306 | mutex_lock(&ad714x->mutex); | ||
1307 | |||
1308 | data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3; | ||
1309 | ad714x->write(ad714x->dev, AD714X_PWR_CTRL, data); | ||
1310 | |||
1311 | mutex_unlock(&ad714x->mutex); | ||
1312 | |||
1313 | return 0; | ||
1314 | } | ||
1315 | EXPORT_SYMBOL(ad714x_disable); | ||
1316 | |||
1317 | int ad714x_enable(struct ad714x_chip *ad714x) | ||
1318 | { | ||
1319 | unsigned short data; | ||
1320 | |||
1321 | dev_dbg(ad714x->dev, "%s enter\n", __func__); | ||
1322 | |||
1323 | mutex_lock(&ad714x->mutex); | ||
1324 | |||
1325 | /* resume to non-shutdown mode */ | ||
1326 | |||
1327 | ad714x->write(ad714x->dev, AD714X_PWR_CTRL, | ||
1328 | ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL]); | ||
1329 | |||
1330 | /* make sure the interrupt output line is not low level after resume, | ||
1331 | * otherwise we will get no chance to enter falling-edge irq again | ||
1332 | */ | ||
1333 | |||
1334 | ad714x->read(ad714x->dev, STG_LOW_INT_STA_REG, &data); | ||
1335 | ad714x->read(ad714x->dev, STG_HIGH_INT_STA_REG, &data); | ||
1336 | ad714x->read(ad714x->dev, STG_COM_INT_STA_REG, &data); | ||
1337 | |||
1338 | mutex_unlock(&ad714x->mutex); | ||
1339 | |||
1340 | return 0; | ||
1341 | } | ||
1342 | EXPORT_SYMBOL(ad714x_enable); | ||
1343 | #endif | ||
1344 | |||
1345 | MODULE_DESCRIPTION("Analog Devices AD714X Capacitance Touch Sensor Driver"); | ||
1346 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
1347 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/ad714x.h b/drivers/input/misc/ad714x.h new file mode 100644 index 00000000000..45c54fb13f0 --- /dev/null +++ b/drivers/input/misc/ad714x.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * AD714X CapTouch Programmable Controller driver (bus interfaces) | ||
3 | * | ||
4 | * Copyright 2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef _AD714X_H_ | ||
10 | #define _AD714X_H_ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | |||
14 | struct device; | ||
15 | struct ad714x_chip; | ||
16 | |||
17 | typedef int (*ad714x_read_t)(struct device *, unsigned short, unsigned short *); | ||
18 | typedef int (*ad714x_write_t)(struct device *, unsigned short, unsigned short); | ||
19 | |||
20 | int ad714x_disable(struct ad714x_chip *ad714x); | ||
21 | int ad714x_enable(struct ad714x_chip *ad714x); | ||
22 | struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq, | ||
23 | ad714x_read_t read, ad714x_write_t write); | ||
24 | void ad714x_remove(struct ad714x_chip *ad714x); | ||
25 | |||
26 | #endif | ||
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index 614b65d78fe..bce57129afb 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c | |||
@@ -98,10 +98,12 @@ | |||
98 | * Module and Version Information, Module Parameters | 98 | * Module and Version Information, Module Parameters |
99 | */ | 99 | */ |
100 | 100 | ||
101 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | 101 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 |
102 | #define ATI_REMOTE_PRODUCT_ID 0x004 | 102 | #define LOLA_REMOTE_PRODUCT_ID 0x0002 |
103 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | 103 | #define LOLA2_REMOTE_PRODUCT_ID 0x0003 |
104 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | 104 | #define ATI_REMOTE_PRODUCT_ID 0x0004 |
105 | #define NVIDIA_REMOTE_PRODUCT_ID 0x0005 | ||
106 | #define MEDION_REMOTE_PRODUCT_ID 0x0006 | ||
105 | 107 | ||
106 | #define DRIVER_VERSION "2.2.1" | 108 | #define DRIVER_VERSION "2.2.1" |
107 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" |
@@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec | |||
142 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 144 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
143 | 145 | ||
144 | static struct usb_device_id ati_remote_table[] = { | 146 | static struct usb_device_id ati_remote_table[] = { |
145 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
146 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | 147 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, |
148 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) }, | ||
149 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
150 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) }, | ||
147 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, | 151 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, |
148 | {} /* Terminating entry */ | 152 | {} /* Terminating entry */ |
149 | }; | 153 | }; |
@@ -620,13 +624,13 @@ static void ati_remote_irq_in(struct urb *urb) | |||
620 | static int ati_remote_alloc_buffers(struct usb_device *udev, | 624 | static int ati_remote_alloc_buffers(struct usb_device *udev, |
621 | struct ati_remote *ati_remote) | 625 | struct ati_remote *ati_remote) |
622 | { | 626 | { |
623 | ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, | 627 | ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, |
624 | &ati_remote->inbuf_dma); | 628 | &ati_remote->inbuf_dma); |
625 | if (!ati_remote->inbuf) | 629 | if (!ati_remote->inbuf) |
626 | return -1; | 630 | return -1; |
627 | 631 | ||
628 | ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, | 632 | ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC, |
629 | &ati_remote->outbuf_dma); | 633 | &ati_remote->outbuf_dma); |
630 | if (!ati_remote->outbuf) | 634 | if (!ati_remote->outbuf) |
631 | return -1; | 635 | return -1; |
632 | 636 | ||
@@ -649,10 +653,10 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote) | |||
649 | usb_free_urb(ati_remote->irq_urb); | 653 | usb_free_urb(ati_remote->irq_urb); |
650 | usb_free_urb(ati_remote->out_urb); | 654 | usb_free_urb(ati_remote->out_urb); |
651 | 655 | ||
652 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 656 | usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, |
653 | ati_remote->inbuf, ati_remote->inbuf_dma); | 657 | ati_remote->inbuf, ati_remote->inbuf_dma); |
654 | 658 | ||
655 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 659 | usb_free_coherent(ati_remote->udev, DATA_BUFSIZE, |
656 | ati_remote->outbuf, ati_remote->outbuf_dma); | 660 | ati_remote->outbuf, ati_remote->outbuf_dma); |
657 | } | 661 | } |
658 | 662 | ||
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 2124b99378b..e148749b585 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
@@ -589,7 +589,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2) | |||
589 | int i, pipe, maxp; | 589 | int i, pipe, maxp; |
590 | 590 | ||
591 | for (i = 0; i < 2; i++) { | 591 | for (i = 0; i < 2; i++) { |
592 | ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); | 592 | ar2->buf[i] = usb_alloc_coherent(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]); |
593 | if (!ar2->buf[i]) | 593 | if (!ar2->buf[i]) |
594 | return -ENOMEM; | 594 | return -ENOMEM; |
595 | 595 | ||
@@ -617,7 +617,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) | |||
617 | 617 | ||
618 | for (i = 0; i < 2; i++) { | 618 | for (i = 0; i < 2; i++) { |
619 | usb_free_urb(ar2->urb[i]); | 619 | usb_free_urb(ar2->urb[i]); |
620 | usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); | 620 | usb_free_coherent(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); |
621 | } | 621 | } |
622 | } | 622 | } |
623 | 623 | ||
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 86457feccfc..2b0eba6619b 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c | |||
@@ -102,7 +102,6 @@ struct cm109_dev { | |||
102 | struct cm109_ctl_packet *ctl_data; | 102 | struct cm109_ctl_packet *ctl_data; |
103 | dma_addr_t ctl_dma; | 103 | dma_addr_t ctl_dma; |
104 | struct usb_ctrlrequest *ctl_req; | 104 | struct usb_ctrlrequest *ctl_req; |
105 | dma_addr_t ctl_req_dma; | ||
106 | struct urb *urb_ctl; | 105 | struct urb *urb_ctl; |
107 | /* | 106 | /* |
108 | * The 3 bitfields below are protected by ctl_submit_lock. | 107 | * The 3 bitfields below are protected by ctl_submit_lock. |
@@ -629,15 +628,13 @@ static const struct usb_device_id cm109_usb_table[] = { | |||
629 | 628 | ||
630 | static void cm109_usb_cleanup(struct cm109_dev *dev) | 629 | static void cm109_usb_cleanup(struct cm109_dev *dev) |
631 | { | 630 | { |
632 | if (dev->ctl_req) | 631 | kfree(dev->ctl_req); |
633 | usb_buffer_free(dev->udev, sizeof(*(dev->ctl_req)), | ||
634 | dev->ctl_req, dev->ctl_req_dma); | ||
635 | if (dev->ctl_data) | 632 | if (dev->ctl_data) |
636 | usb_buffer_free(dev->udev, USB_PKT_LEN, | 633 | usb_free_coherent(dev->udev, USB_PKT_LEN, |
637 | dev->ctl_data, dev->ctl_dma); | 634 | dev->ctl_data, dev->ctl_dma); |
638 | if (dev->irq_data) | 635 | if (dev->irq_data) |
639 | usb_buffer_free(dev->udev, USB_PKT_LEN, | 636 | usb_free_coherent(dev->udev, USB_PKT_LEN, |
640 | dev->irq_data, dev->irq_dma); | 637 | dev->irq_data, dev->irq_dma); |
641 | 638 | ||
642 | usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ | 639 | usb_free_urb(dev->urb_irq); /* parameter validation in core/urb */ |
643 | usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ | 640 | usb_free_urb(dev->urb_ctl); /* parameter validation in core/urb */ |
@@ -686,18 +683,17 @@ static int cm109_usb_probe(struct usb_interface *intf, | |||
686 | goto err_out; | 683 | goto err_out; |
687 | 684 | ||
688 | /* allocate usb buffers */ | 685 | /* allocate usb buffers */ |
689 | dev->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, | 686 | dev->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, |
690 | GFP_KERNEL, &dev->irq_dma); | 687 | GFP_KERNEL, &dev->irq_dma); |
691 | if (!dev->irq_data) | 688 | if (!dev->irq_data) |
692 | goto err_out; | 689 | goto err_out; |
693 | 690 | ||
694 | dev->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, | 691 | dev->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, |
695 | GFP_KERNEL, &dev->ctl_dma); | 692 | GFP_KERNEL, &dev->ctl_dma); |
696 | if (!dev->ctl_data) | 693 | if (!dev->ctl_data) |
697 | goto err_out; | 694 | goto err_out; |
698 | 695 | ||
699 | dev->ctl_req = usb_buffer_alloc(udev, sizeof(*(dev->ctl_req)), | 696 | dev->ctl_req = kmalloc(sizeof(*(dev->ctl_req)), GFP_KERNEL); |
700 | GFP_KERNEL, &dev->ctl_req_dma); | ||
701 | if (!dev->ctl_req) | 697 | if (!dev->ctl_req) |
702 | goto err_out; | 698 | goto err_out; |
703 | 699 | ||
@@ -735,10 +731,8 @@ static int cm109_usb_probe(struct usb_interface *intf, | |||
735 | usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), | 731 | usb_fill_control_urb(dev->urb_ctl, udev, usb_sndctrlpipe(udev, 0), |
736 | (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, | 732 | (void *)dev->ctl_req, dev->ctl_data, USB_PKT_LEN, |
737 | cm109_urb_ctl_callback, dev); | 733 | cm109_urb_ctl_callback, dev); |
738 | dev->urb_ctl->setup_dma = dev->ctl_req_dma; | ||
739 | dev->urb_ctl->transfer_dma = dev->ctl_dma; | 734 | dev->urb_ctl->transfer_dma = dev->ctl_dma; |
740 | dev->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | | 735 | dev->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
741 | URB_NO_TRANSFER_DMA_MAP; | ||
742 | dev->urb_ctl->dev = udev; | 736 | dev->urb_ctl->dev = udev; |
743 | 737 | ||
744 | /* find out the physical bus location */ | 738 | /* find out the physical bus location */ |
diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index 86afdd1fdf9..a93c525475c 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c | |||
@@ -464,7 +464,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic | |||
464 | remote->in_endpoint = endpoint; | 464 | remote->in_endpoint = endpoint; |
465 | remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ | 465 | remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ |
466 | 466 | ||
467 | remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); | 467 | remote->in_buffer = usb_alloc_coherent(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); |
468 | if (!remote->in_buffer) { | 468 | if (!remote->in_buffer) { |
469 | error = -ENOMEM; | 469 | error = -ENOMEM; |
470 | goto fail1; | 470 | goto fail1; |
@@ -543,7 +543,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic | |||
543 | return 0; | 543 | return 0; |
544 | 544 | ||
545 | fail3: usb_free_urb(remote->irq_urb); | 545 | fail3: usb_free_urb(remote->irq_urb); |
546 | fail2: usb_buffer_free(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | 546 | fail2: usb_free_coherent(udev, RECV_SIZE, remote->in_buffer, remote->in_dma); |
547 | fail1: kfree(remote); | 547 | fail1: kfree(remote); |
548 | input_free_device(input_dev); | 548 | input_free_device(input_dev); |
549 | 549 | ||
@@ -564,7 +564,7 @@ static void keyspan_disconnect(struct usb_interface *interface) | |||
564 | input_unregister_device(remote->input); | 564 | input_unregister_device(remote->input); |
565 | usb_kill_urb(remote->irq_urb); | 565 | usb_kill_urb(remote->irq_urb); |
566 | usb_free_urb(remote->irq_urb); | 566 | usb_free_urb(remote->irq_urb); |
567 | usb_buffer_free(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); | 567 | usb_free_coherent(remote->udev, RECV_SIZE, remote->in_buffer, remote->in_dma); |
568 | kfree(remote); | 568 | kfree(remote); |
569 | } | 569 | } |
570 | } | 570 | } |
diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c new file mode 100644 index 00000000000..5c3ac4e0b05 --- /dev/null +++ b/drivers/input/misc/pcf8574_keypad.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * Driver for a keypad w/16 buttons connected to a PCF8574 I2C I/O expander | ||
3 | * | ||
4 | * Copyright 2005-2008 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/input.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/workqueue.h> | ||
16 | |||
17 | #define DRV_NAME "pcf8574_keypad" | ||
18 | |||
19 | static const unsigned char pcf8574_kp_btncode[] = { | ||
20 | [0] = KEY_RESERVED, | ||
21 | [1] = KEY_ENTER, | ||
22 | [2] = KEY_BACKSLASH, | ||
23 | [3] = KEY_0, | ||
24 | [4] = KEY_RIGHTBRACE, | ||
25 | [5] = KEY_C, | ||
26 | [6] = KEY_9, | ||
27 | [7] = KEY_8, | ||
28 | [8] = KEY_7, | ||
29 | [9] = KEY_B, | ||
30 | [10] = KEY_6, | ||
31 | [11] = KEY_5, | ||
32 | [12] = KEY_4, | ||
33 | [13] = KEY_A, | ||
34 | [14] = KEY_3, | ||
35 | [15] = KEY_2, | ||
36 | [16] = KEY_1 | ||
37 | }; | ||
38 | |||
39 | struct kp_data { | ||
40 | unsigned short btncode[ARRAY_SIZE(pcf8574_kp_btncode)]; | ||
41 | struct input_dev *idev; | ||
42 | struct i2c_client *client; | ||
43 | char name[64]; | ||
44 | char phys[32]; | ||
45 | unsigned char laststate; | ||
46 | }; | ||
47 | |||
48 | static short read_state(struct kp_data *lp) | ||
49 | { | ||
50 | unsigned char x, y, a, b; | ||
51 | |||
52 | i2c_smbus_write_byte(lp->client, 240); | ||
53 | x = 0xF & (~(i2c_smbus_read_byte(lp->client) >> 4)); | ||
54 | |||
55 | i2c_smbus_write_byte(lp->client, 15); | ||
56 | y = 0xF & (~i2c_smbus_read_byte(lp->client)); | ||
57 | |||
58 | for (a = 0; x > 0; a++) | ||
59 | x = x >> 1; | ||
60 | for (b = 0; y > 0; b++) | ||
61 | y = y >> 1; | ||
62 | |||
63 | return ((a - 1) * 4) + b; | ||
64 | } | ||
65 | |||
66 | static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id) | ||
67 | { | ||
68 | struct kp_data *lp = dev_id; | ||
69 | unsigned char nextstate = read_state(lp); | ||
70 | |||
71 | if (lp->laststate != nextstate) { | ||
72 | int key_down = nextstate <= ARRAY_SIZE(lp->btncode); | ||
73 | unsigned short keycode = key_down ? | ||
74 | lp->btncode[nextstate] : lp->btncode[lp->laststate]; | ||
75 | |||
76 | input_report_key(lp->idev, keycode, key_down); | ||
77 | input_sync(lp->idev); | ||
78 | |||
79 | lp->laststate = nextstate; | ||
80 | } | ||
81 | |||
82 | return IRQ_HANDLED; | ||
83 | } | ||
84 | |||
85 | static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
86 | { | ||
87 | int i, ret; | ||
88 | struct input_dev *idev; | ||
89 | struct kp_data *lp; | ||
90 | |||
91 | if (i2c_smbus_write_byte(client, 240) < 0) { | ||
92 | dev_err(&client->dev, "probe: write fail\n"); | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | |||
96 | lp = kzalloc(sizeof(*lp), GFP_KERNEL); | ||
97 | if (!lp) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | idev = input_allocate_device(); | ||
101 | if (!idev) { | ||
102 | dev_err(&client->dev, "Can't allocate input device\n"); | ||
103 | ret = -ENOMEM; | ||
104 | goto fail_allocate; | ||
105 | } | ||
106 | |||
107 | lp->idev = idev; | ||
108 | lp->client = client; | ||
109 | |||
110 | idev->evbit[0] = BIT_MASK(EV_KEY); | ||
111 | idev->keycode = lp->btncode; | ||
112 | idev->keycodesize = sizeof(lp->btncode[0]); | ||
113 | idev->keycodemax = ARRAY_SIZE(lp->btncode); | ||
114 | |||
115 | for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) { | ||
116 | lp->btncode[i] = pcf8574_kp_btncode[i]; | ||
117 | __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit); | ||
118 | } | ||
119 | |||
120 | sprintf(lp->name, DRV_NAME); | ||
121 | sprintf(lp->phys, "kp_data/input0"); | ||
122 | |||
123 | idev->name = lp->name; | ||
124 | idev->phys = lp->phys; | ||
125 | idev->id.bustype = BUS_I2C; | ||
126 | idev->id.vendor = 0x0001; | ||
127 | idev->id.product = 0x0001; | ||
128 | idev->id.version = 0x0100; | ||
129 | |||
130 | input_set_drvdata(idev, lp); | ||
131 | |||
132 | ret = input_register_device(idev); | ||
133 | if (ret) { | ||
134 | dev_err(&client->dev, "input_register_device() failed\n"); | ||
135 | goto fail_register; | ||
136 | } | ||
137 | |||
138 | lp->laststate = read_state(lp); | ||
139 | |||
140 | ret = request_threaded_irq(client->irq, NULL, pcf8574_kp_irq_handler, | ||
141 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
142 | DRV_NAME, lp); | ||
143 | if (ret) { | ||
144 | dev_err(&client->dev, "IRQ %d is not free\n", client->irq); | ||
145 | goto fail_irq; | ||
146 | } | ||
147 | |||
148 | i2c_set_clientdata(client, lp); | ||
149 | return 0; | ||
150 | |||
151 | fail_irq: | ||
152 | input_unregister_device(idev); | ||
153 | fail_register: | ||
154 | input_set_drvdata(idev, NULL); | ||
155 | input_free_device(idev); | ||
156 | fail_allocate: | ||
157 | kfree(lp); | ||
158 | |||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static int __devexit pcf8574_kp_remove(struct i2c_client *client) | ||
163 | { | ||
164 | struct kp_data *lp = i2c_get_clientdata(client); | ||
165 | |||
166 | free_irq(client->irq, lp); | ||
167 | |||
168 | input_unregister_device(lp->idev); | ||
169 | kfree(lp); | ||
170 | |||
171 | i2c_set_clientdata(client, NULL); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | #ifdef CONFIG_PM | ||
177 | static int pcf8574_kp_resume(struct i2c_client *client) | ||
178 | { | ||
179 | enable_irq(client->irq); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int pcf8574_kp_suspend(struct i2c_client *client, pm_message_t mesg) | ||
185 | { | ||
186 | disable_irq(client->irq); | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | #else | ||
191 | # define pcf8574_kp_resume NULL | ||
192 | # define pcf8574_kp_suspend NULL | ||
193 | #endif | ||
194 | |||
195 | static const struct i2c_device_id pcf8574_kp_id[] = { | ||
196 | { DRV_NAME, 0 }, | ||
197 | { } | ||
198 | }; | ||
199 | MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id); | ||
200 | |||
201 | static struct i2c_driver pcf8574_kp_driver = { | ||
202 | .driver = { | ||
203 | .name = DRV_NAME, | ||
204 | .owner = THIS_MODULE, | ||
205 | }, | ||
206 | .probe = pcf8574_kp_probe, | ||
207 | .remove = __devexit_p(pcf8574_kp_remove), | ||
208 | .suspend = pcf8574_kp_suspend, | ||
209 | .resume = pcf8574_kp_resume, | ||
210 | .id_table = pcf8574_kp_id, | ||
211 | }; | ||
212 | |||
213 | static int __init pcf8574_kp_init(void) | ||
214 | { | ||
215 | return i2c_add_driver(&pcf8574_kp_driver); | ||
216 | } | ||
217 | module_init(pcf8574_kp_init); | ||
218 | |||
219 | static void __exit pcf8574_kp_exit(void) | ||
220 | { | ||
221 | i2c_del_driver(&pcf8574_kp_driver); | ||
222 | } | ||
223 | module_exit(pcf8574_kp_exit); | ||
224 | |||
225 | MODULE_AUTHOR("Michael Hennerich"); | ||
226 | MODULE_DESCRIPTION("Keypad input driver for 16 keys connected to PCF8574"); | ||
227 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd1265..f080dd31499 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr"); | |||
30 | #include <asm/i8253.h> | 30 | #include <asm/i8253.h> |
31 | #else | 31 | #else |
32 | #include <asm/8253pit.h> | 32 | #include <asm/8253pit.h> |
33 | static DEFINE_SPINLOCK(i8253_lock); | 33 | static DEFINE_RAW_SPINLOCK(i8253_lock); |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
@@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
50 | if (value > 20 && value < 32767) | 50 | if (value > 20 && value < 32767) |
51 | count = PIT_TICK_RATE / value; | 51 | count = PIT_TICK_RATE / value; |
52 | 52 | ||
53 | spin_lock_irqsave(&i8253_lock, flags); | 53 | raw_spin_lock_irqsave(&i8253_lock, flags); |
54 | 54 | ||
55 | if (count) { | 55 | if (count) { |
56 | /* set command for counter 2, 2 byte write */ | 56 | /* set command for counter 2, 2 byte write */ |
@@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
65 | outb(inb_p(0x61) & 0xFC, 0x61); | 65 | outb(inb_p(0x61) & 0xFC, 0x61); |
66 | } | 66 | } |
67 | 67 | ||
68 | spin_unlock_irqrestore(&i8253_lock, flags); | 68 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
69 | 69 | ||
70 | return 0; | 70 | return 0; |
71 | } | 71 | } |
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 668913d1204..bf170f6b442 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c | |||
@@ -64,7 +64,6 @@ struct powermate_device { | |||
64 | dma_addr_t data_dma; | 64 | dma_addr_t data_dma; |
65 | struct urb *irq, *config; | 65 | struct urb *irq, *config; |
66 | struct usb_ctrlrequest *configcr; | 66 | struct usb_ctrlrequest *configcr; |
67 | dma_addr_t configcr_dma; | ||
68 | struct usb_device *udev; | 67 | struct usb_device *udev; |
69 | struct input_dev *input; | 68 | struct input_dev *input; |
70 | spinlock_t lock; | 69 | spinlock_t lock; |
@@ -182,8 +181,6 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
182 | usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), | 181 | usb_fill_control_urb(pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), |
183 | (void *) pm->configcr, NULL, 0, | 182 | (void *) pm->configcr, NULL, 0, |
184 | powermate_config_complete, pm); | 183 | powermate_config_complete, pm); |
185 | pm->config->setup_dma = pm->configcr_dma; | ||
186 | pm->config->transfer_flags |= URB_NO_SETUP_DMA_MAP; | ||
187 | 184 | ||
188 | if (usb_submit_urb(pm->config, GFP_ATOMIC)) | 185 | if (usb_submit_urb(pm->config, GFP_ATOMIC)) |
189 | printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); | 186 | printk(KERN_ERR "powermate: usb_submit_urb(config) failed"); |
@@ -276,13 +273,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig | |||
276 | 273 | ||
277 | static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) | 274 | static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) |
278 | { | 275 | { |
279 | pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, | 276 | pm->data = usb_alloc_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, |
280 | GFP_ATOMIC, &pm->data_dma); | 277 | GFP_ATOMIC, &pm->data_dma); |
281 | if (!pm->data) | 278 | if (!pm->data) |
282 | return -1; | 279 | return -1; |
283 | 280 | ||
284 | pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), | 281 | pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL); |
285 | GFP_ATOMIC, &pm->configcr_dma); | ||
286 | if (!pm->configcr) | 282 | if (!pm->configcr) |
287 | return -1; | 283 | return -1; |
288 | 284 | ||
@@ -291,10 +287,9 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev | |||
291 | 287 | ||
292 | static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) | 288 | static void powermate_free_buffers(struct usb_device *udev, struct powermate_device *pm) |
293 | { | 289 | { |
294 | usb_buffer_free(udev, POWERMATE_PAYLOAD_SIZE_MAX, | 290 | usb_free_coherent(udev, POWERMATE_PAYLOAD_SIZE_MAX, |
295 | pm->data, pm->data_dma); | 291 | pm->data, pm->data_dma); |
296 | usb_buffer_free(udev, sizeof(*(pm->configcr)), | 292 | kfree(pm->configcr); |
297 | pm->configcr, pm->configcr_dma); | ||
298 | } | 293 | } |
299 | 294 | ||
300 | /* Called whenever a USB device matching one in our supported devices table is connected */ | 295 | /* Called whenever a USB device matching one in our supported devices table is connected */ |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 04d5a4a3181..4dac8b79fcd 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -983,11 +983,11 @@ static int __init copy_keymap(void) | |||
983 | for (key = keymap; key->type != KE_END; key++) | 983 | for (key = keymap; key->type != KE_END; key++) |
984 | length++; | 984 | length++; |
985 | 985 | ||
986 | new_keymap = kmalloc(length * sizeof(struct key_entry), GFP_KERNEL); | 986 | new_keymap = kmemdup(keymap, length * sizeof(struct key_entry), |
987 | GFP_KERNEL); | ||
987 | if (!new_keymap) | 988 | if (!new_keymap) |
988 | return -ENOMEM; | 989 | return -ENOMEM; |
989 | 990 | ||
990 | memcpy(new_keymap, keymap, length * sizeof(struct key_entry)); | ||
991 | keymap = new_keymap; | 991 | keymap = new_keymap; |
992 | 992 | ||
993 | return 0; | 993 | return 0; |
diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 93a22ac0f88..41201c6b5e6 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c | |||
@@ -111,7 +111,6 @@ struct yealink_dev { | |||
111 | struct yld_ctl_packet *ctl_data; | 111 | struct yld_ctl_packet *ctl_data; |
112 | dma_addr_t ctl_dma; | 112 | dma_addr_t ctl_dma; |
113 | struct usb_ctrlrequest *ctl_req; | 113 | struct usb_ctrlrequest *ctl_req; |
114 | dma_addr_t ctl_req_dma; | ||
115 | struct urb *urb_ctl; | 114 | struct urb *urb_ctl; |
116 | 115 | ||
117 | char phys[64]; /* physical device path */ | 116 | char phys[64]; /* physical device path */ |
@@ -836,12 +835,9 @@ static int usb_cleanup(struct yealink_dev *yld, int err) | |||
836 | usb_free_urb(yld->urb_irq); | 835 | usb_free_urb(yld->urb_irq); |
837 | usb_free_urb(yld->urb_ctl); | 836 | usb_free_urb(yld->urb_ctl); |
838 | 837 | ||
839 | usb_buffer_free(yld->udev, sizeof(*(yld->ctl_req)), | 838 | kfree(yld->ctl_req); |
840 | yld->ctl_req, yld->ctl_req_dma); | 839 | usb_free_coherent(yld->udev, USB_PKT_LEN, yld->ctl_data, yld->ctl_dma); |
841 | usb_buffer_free(yld->udev, USB_PKT_LEN, | 840 | usb_free_coherent(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma); |
842 | yld->ctl_data, yld->ctl_dma); | ||
843 | usb_buffer_free(yld->udev, USB_PKT_LEN, | ||
844 | yld->irq_data, yld->irq_dma); | ||
845 | 841 | ||
846 | kfree(yld); | 842 | kfree(yld); |
847 | return err; | 843 | return err; |
@@ -886,18 +882,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
886 | return usb_cleanup(yld, -ENOMEM); | 882 | return usb_cleanup(yld, -ENOMEM); |
887 | 883 | ||
888 | /* allocate usb buffers */ | 884 | /* allocate usb buffers */ |
889 | yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, | 885 | yld->irq_data = usb_alloc_coherent(udev, USB_PKT_LEN, |
890 | GFP_ATOMIC, &yld->irq_dma); | 886 | GFP_ATOMIC, &yld->irq_dma); |
891 | if (yld->irq_data == NULL) | 887 | if (yld->irq_data == NULL) |
892 | return usb_cleanup(yld, -ENOMEM); | 888 | return usb_cleanup(yld, -ENOMEM); |
893 | 889 | ||
894 | yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, | 890 | yld->ctl_data = usb_alloc_coherent(udev, USB_PKT_LEN, |
895 | GFP_ATOMIC, &yld->ctl_dma); | 891 | GFP_ATOMIC, &yld->ctl_dma); |
896 | if (!yld->ctl_data) | 892 | if (!yld->ctl_data) |
897 | return usb_cleanup(yld, -ENOMEM); | 893 | return usb_cleanup(yld, -ENOMEM); |
898 | 894 | ||
899 | yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), | 895 | yld->ctl_req = kmalloc(sizeof(*(yld->ctl_req)), GFP_KERNEL); |
900 | GFP_ATOMIC, &yld->ctl_req_dma); | ||
901 | if (yld->ctl_req == NULL) | 896 | if (yld->ctl_req == NULL) |
902 | return usb_cleanup(yld, -ENOMEM); | 897 | return usb_cleanup(yld, -ENOMEM); |
903 | 898 | ||
@@ -936,10 +931,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
936 | usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), | 931 | usb_fill_control_urb(yld->urb_ctl, udev, usb_sndctrlpipe(udev, 0), |
937 | (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, | 932 | (void *)yld->ctl_req, yld->ctl_data, USB_PKT_LEN, |
938 | urb_ctl_callback, yld); | 933 | urb_ctl_callback, yld); |
939 | yld->urb_ctl->setup_dma = yld->ctl_req_dma; | ||
940 | yld->urb_ctl->transfer_dma = yld->ctl_dma; | 934 | yld->urb_ctl->transfer_dma = yld->ctl_dma; |
941 | yld->urb_ctl->transfer_flags |= URB_NO_SETUP_DMA_MAP | | 935 | yld->urb_ctl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
942 | URB_NO_TRANSFER_DMA_MAP; | ||
943 | yld->urb_ctl->dev = udev; | 936 | yld->urb_ctl->dev = udev; |
944 | 937 | ||
945 | /* find out the physical bus location */ | 938 | /* find out the physical bus location */ |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index c714ca2407f..eeb58c1cac1 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -17,7 +17,7 @@ config MOUSE_PS2 | |||
17 | default y | 17 | default y |
18 | select SERIO | 18 | select SERIO |
19 | select SERIO_LIBPS2 | 19 | select SERIO_LIBPS2 |
20 | select SERIO_I8042 if X86 | 20 | select SERIO_I8042 if X86 && !X86_MRST |
21 | select SERIO_GSCPS2 if GSC | 21 | select SERIO_GSCPS2 if GSC |
22 | help | 22 | help |
23 | Say Y here if you have a PS/2 mouse connected to your system. This | 23 | Say Y here if you have a PS/2 mouse connected to your system. This |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 0d22cb9ce42..99d58764ef0 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -64,7 +64,6 @@ static const struct alps_model_info alps_model_data[] = { | |||
64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, | 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, |
65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, |
66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
67 | { { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */ | ||
68 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, | 67 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, |
69 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | 68 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ |
70 | }; | 69 | }; |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 53ec7ddd182..05edd75abca 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -806,8 +806,8 @@ static int atp_probe(struct usb_interface *iface, | |||
806 | if (!dev->urb) | 806 | if (!dev->urb) |
807 | goto err_free_devs; | 807 | goto err_free_devs; |
808 | 808 | ||
809 | dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL, | 809 | dev->data = usb_alloc_coherent(dev->udev, dev->info->datalen, GFP_KERNEL, |
810 | &dev->urb->transfer_dma); | 810 | &dev->urb->transfer_dma); |
811 | if (!dev->data) | 811 | if (!dev->data) |
812 | goto err_free_urb; | 812 | goto err_free_urb; |
813 | 813 | ||
@@ -862,8 +862,8 @@ static int atp_probe(struct usb_interface *iface, | |||
862 | return 0; | 862 | return 0; |
863 | 863 | ||
864 | err_free_buffer: | 864 | err_free_buffer: |
865 | usb_buffer_free(dev->udev, dev->info->datalen, | 865 | usb_free_coherent(dev->udev, dev->info->datalen, |
866 | dev->data, dev->urb->transfer_dma); | 866 | dev->data, dev->urb->transfer_dma); |
867 | err_free_urb: | 867 | err_free_urb: |
868 | usb_free_urb(dev->urb); | 868 | usb_free_urb(dev->urb); |
869 | err_free_devs: | 869 | err_free_devs: |
@@ -881,8 +881,8 @@ static void atp_disconnect(struct usb_interface *iface) | |||
881 | if (dev) { | 881 | if (dev) { |
882 | usb_kill_urb(dev->urb); | 882 | usb_kill_urb(dev->urb); |
883 | input_unregister_device(dev->input); | 883 | input_unregister_device(dev->input); |
884 | usb_buffer_free(dev->udev, dev->info->datalen, | 884 | usb_free_coherent(dev->udev, dev->info->datalen, |
885 | dev->data, dev->urb->transfer_dma); | 885 | dev->data, dev->urb->transfer_dma); |
886 | usb_free_urb(dev->urb); | 886 | usb_free_urb(dev->urb); |
887 | kfree(dev); | 887 | kfree(dev); |
888 | } | 888 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index b89879bd860..6dedded2722 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -715,15 +715,15 @@ static int bcm5974_probe(struct usb_interface *iface, | |||
715 | if (!dev->tp_urb) | 715 | if (!dev->tp_urb) |
716 | goto err_free_bt_urb; | 716 | goto err_free_bt_urb; |
717 | 717 | ||
718 | dev->bt_data = usb_buffer_alloc(dev->udev, | 718 | dev->bt_data = usb_alloc_coherent(dev->udev, |
719 | dev->cfg.bt_datalen, GFP_KERNEL, | 719 | dev->cfg.bt_datalen, GFP_KERNEL, |
720 | &dev->bt_urb->transfer_dma); | 720 | &dev->bt_urb->transfer_dma); |
721 | if (!dev->bt_data) | 721 | if (!dev->bt_data) |
722 | goto err_free_urb; | 722 | goto err_free_urb; |
723 | 723 | ||
724 | dev->tp_data = usb_buffer_alloc(dev->udev, | 724 | dev->tp_data = usb_alloc_coherent(dev->udev, |
725 | dev->cfg.tp_datalen, GFP_KERNEL, | 725 | dev->cfg.tp_datalen, GFP_KERNEL, |
726 | &dev->tp_urb->transfer_dma); | 726 | &dev->tp_urb->transfer_dma); |
727 | if (!dev->tp_data) | 727 | if (!dev->tp_data) |
728 | goto err_free_bt_buffer; | 728 | goto err_free_bt_buffer; |
729 | 729 | ||
@@ -765,10 +765,10 @@ static int bcm5974_probe(struct usb_interface *iface, | |||
765 | return 0; | 765 | return 0; |
766 | 766 | ||
767 | err_free_buffer: | 767 | err_free_buffer: |
768 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | 768 | usb_free_coherent(dev->udev, dev->cfg.tp_datalen, |
769 | dev->tp_data, dev->tp_urb->transfer_dma); | 769 | dev->tp_data, dev->tp_urb->transfer_dma); |
770 | err_free_bt_buffer: | 770 | err_free_bt_buffer: |
771 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | 771 | usb_free_coherent(dev->udev, dev->cfg.bt_datalen, |
772 | dev->bt_data, dev->bt_urb->transfer_dma); | 772 | dev->bt_data, dev->bt_urb->transfer_dma); |
773 | err_free_urb: | 773 | err_free_urb: |
774 | usb_free_urb(dev->tp_urb); | 774 | usb_free_urb(dev->tp_urb); |
@@ -788,10 +788,10 @@ static void bcm5974_disconnect(struct usb_interface *iface) | |||
788 | usb_set_intfdata(iface, NULL); | 788 | usb_set_intfdata(iface, NULL); |
789 | 789 | ||
790 | input_unregister_device(dev->input); | 790 | input_unregister_device(dev->input); |
791 | usb_buffer_free(dev->udev, dev->cfg.tp_datalen, | 791 | usb_free_coherent(dev->udev, dev->cfg.tp_datalen, |
792 | dev->tp_data, dev->tp_urb->transfer_dma); | 792 | dev->tp_data, dev->tp_urb->transfer_dma); |
793 | usb_buffer_free(dev->udev, dev->cfg.bt_datalen, | 793 | usb_free_coherent(dev->udev, dev->cfg.bt_datalen, |
794 | dev->bt_data, dev->bt_urb->transfer_dma); | 794 | dev->bt_data, dev->bt_urb->transfer_dma); |
795 | usb_free_urb(dev->tp_urb); | 795 | usb_free_urb(dev->tp_urb); |
796 | usb_free_urb(dev->bt_urb); | 796 | usb_free_urb(dev->bt_urb); |
797 | kfree(dev); | 797 | kfree(dev); |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a138b5da79f..b18862b2a70 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -10,6 +10,8 @@ | |||
10 | * Trademarks are the property of their respective owners. | 10 | * Trademarks are the property of their respective owners. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt | ||
14 | |||
13 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
14 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
@@ -19,12 +21,16 @@ | |||
19 | #include "psmouse.h" | 21 | #include "psmouse.h" |
20 | #include "elantech.h" | 22 | #include "elantech.h" |
21 | 23 | ||
22 | #define elantech_debug(format, arg...) \ | 24 | #define elantech_debug(fmt, ...) \ |
23 | do { \ | 25 | do { \ |
24 | if (etd->debug) \ | 26 | if (etd->debug) \ |
25 | printk(KERN_DEBUG format, ##arg); \ | 27 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ |
26 | } while (0) | 28 | } while (0) |
27 | 29 | ||
30 | static bool force_elantech; | ||
31 | module_param_named(force_elantech, force_elantech, bool, 0644); | ||
32 | MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); | ||
33 | |||
28 | /* | 34 | /* |
29 | * Send a Synaptics style sliced query command | 35 | * Send a Synaptics style sliced query command |
30 | */ | 36 | */ |
@@ -33,7 +39,7 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, | |||
33 | { | 39 | { |
34 | if (psmouse_sliced_command(psmouse, c) || | 40 | if (psmouse_sliced_command(psmouse, c) || |
35 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 41 | ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
36 | pr_err("elantech.c: synaptics_send_cmd query 0x%02x failed.\n", c); | 42 | pr_err("synaptics_send_cmd query 0x%02x failed.\n", c); |
37 | return -1; | 43 | return -1; |
38 | } | 44 | } |
39 | 45 | ||
@@ -56,13 +62,13 @@ static int elantech_ps2_command(struct psmouse *psmouse, | |||
56 | if (rc == 0) | 62 | if (rc == 0) |
57 | break; | 63 | break; |
58 | tries--; | 64 | tries--; |
59 | elantech_debug("elantech.c: retrying ps2 command 0x%02x (%d).\n", | 65 | elantech_debug("retrying ps2 command 0x%02x (%d).\n", |
60 | command, tries); | 66 | command, tries); |
61 | msleep(ETP_PS2_COMMAND_DELAY); | 67 | msleep(ETP_PS2_COMMAND_DELAY); |
62 | } while (tries > 0); | 68 | } while (tries > 0); |
63 | 69 | ||
64 | if (rc) | 70 | if (rc) |
65 | pr_err("elantech.c: ps2 command 0x%02x failed.\n", command); | 71 | pr_err("ps2 command 0x%02x failed.\n", command); |
66 | 72 | ||
67 | return rc; | 73 | return rc; |
68 | } | 74 | } |
@@ -104,7 +110,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, | |||
104 | } | 110 | } |
105 | 111 | ||
106 | if (rc) | 112 | if (rc) |
107 | pr_err("elantech.c: failed to read register 0x%02x.\n", reg); | 113 | pr_err("failed to read register 0x%02x.\n", reg); |
108 | else | 114 | else |
109 | *val = param[0]; | 115 | *val = param[0]; |
110 | 116 | ||
@@ -150,7 +156,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | |||
150 | } | 156 | } |
151 | 157 | ||
152 | if (rc) | 158 | if (rc) |
153 | pr_err("elantech.c: failed to write register 0x%02x with value 0x%02x.\n", | 159 | pr_err("failed to write register 0x%02x with value 0x%02x.\n", |
154 | reg, val); | 160 | reg, val); |
155 | 161 | ||
156 | return rc; | 162 | return rc; |
@@ -163,7 +169,7 @@ static void elantech_packet_dump(unsigned char *packet, int size) | |||
163 | { | 169 | { |
164 | int i; | 170 | int i; |
165 | 171 | ||
166 | printk(KERN_DEBUG "elantech.c: PS/2 packet ["); | 172 | printk(KERN_DEBUG pr_fmt("PS/2 packet [")); |
167 | for (i = 0; i < size; i++) | 173 | for (i = 0; i < size; i++) |
168 | printk("%s0x%02x ", (i) ? ", " : " ", packet[i]); | 174 | printk("%s0x%02x ", (i) ? ", " : " ", packet[i]); |
169 | printk("]\n"); | 175 | printk("]\n"); |
@@ -181,34 +187,40 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
181 | int fingers; | 187 | int fingers; |
182 | static int old_fingers; | 188 | static int old_fingers; |
183 | 189 | ||
184 | if (etd->fw_version_maj == 0x01) { | 190 | if (etd->fw_version < 0x020000) { |
185 | /* byte 0: D U p1 p2 1 p3 R L | 191 | /* |
186 | byte 1: f 0 th tw x9 x8 y9 y8 */ | 192 | * byte 0: D U p1 p2 1 p3 R L |
193 | * byte 1: f 0 th tw x9 x8 y9 y8 | ||
194 | */ | ||
187 | fingers = ((packet[1] & 0x80) >> 7) + | 195 | fingers = ((packet[1] & 0x80) >> 7) + |
188 | ((packet[1] & 0x30) >> 4); | 196 | ((packet[1] & 0x30) >> 4); |
189 | } else { | 197 | } else { |
190 | /* byte 0: n1 n0 p2 p1 1 p3 R L | 198 | /* |
191 | byte 1: 0 0 0 0 x9 x8 y9 y8 */ | 199 | * byte 0: n1 n0 p2 p1 1 p3 R L |
200 | * byte 1: 0 0 0 0 x9 x8 y9 y8 | ||
201 | */ | ||
192 | fingers = (packet[0] & 0xc0) >> 6; | 202 | fingers = (packet[0] & 0xc0) >> 6; |
193 | } | 203 | } |
194 | 204 | ||
195 | if (etd->jumpy_cursor) { | 205 | if (etd->jumpy_cursor) { |
196 | /* Discard packets that are likely to have bogus coordinates */ | 206 | /* Discard packets that are likely to have bogus coordinates */ |
197 | if (fingers > old_fingers) { | 207 | if (fingers > old_fingers) { |
198 | elantech_debug("elantech.c: discarding packet\n"); | 208 | elantech_debug("discarding packet\n"); |
199 | goto discard_packet_v1; | 209 | goto discard_packet_v1; |
200 | } | 210 | } |
201 | } | 211 | } |
202 | 212 | ||
203 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 213 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
204 | 214 | ||
205 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 215 | /* |
206 | byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ | 216 | * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
217 | * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 | ||
218 | */ | ||
207 | if (fingers) { | 219 | if (fingers) { |
208 | input_report_abs(dev, ABS_X, | 220 | input_report_abs(dev, ABS_X, |
209 | ((packet[1] & 0x0c) << 6) | packet[2]); | 221 | ((packet[1] & 0x0c) << 6) | packet[2]); |
210 | input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - | 222 | input_report_abs(dev, ABS_Y, |
211 | (((packet[1] & 0x03) << 8) | packet[3])); | 223 | ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); |
212 | } | 224 | } |
213 | 225 | ||
214 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 226 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
@@ -217,7 +229,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
217 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 229 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
218 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 230 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
219 | 231 | ||
220 | if ((etd->fw_version_maj == 0x01) && | 232 | if (etd->fw_version < 0x020000 && |
221 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 233 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
222 | /* rocker up */ | 234 | /* rocker up */ |
223 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); | 235 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); |
@@ -247,34 +259,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
247 | 259 | ||
248 | switch (fingers) { | 260 | switch (fingers) { |
249 | case 1: | 261 | case 1: |
250 | /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 | 262 | /* |
251 | byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ | 263 | * byte 1: . . . . . x10 x9 x8 |
252 | input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); | 264 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
253 | /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 | 265 | */ |
254 | byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ | 266 | input_report_abs(dev, ABS_X, |
255 | input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - | 267 | ((packet[1] & 0x07) << 8) | packet[2]); |
256 | ((packet[4] << 8) | packet[5])); | 268 | /* |
269 | * byte 4: . . . . . . y9 y8 | ||
270 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
271 | */ | ||
272 | input_report_abs(dev, ABS_Y, | ||
273 | ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); | ||
257 | break; | 274 | break; |
258 | 275 | ||
259 | case 2: | 276 | case 2: |
260 | /* The coordinate of each finger is reported separately with | 277 | /* |
261 | a lower resolution for two finger touches */ | 278 | * The coordinate of each finger is reported separately |
262 | /* byte 0: . . ay8 ax8 . . . . | 279 | * with a lower resolution for two finger touches: |
263 | byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ | 280 | * byte 0: . . ay8 ax8 . . . . |
281 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | ||
282 | */ | ||
264 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; | 283 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; |
265 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 284 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
266 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); | 285 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); |
267 | /* byte 3: . . by8 bx8 . . . . | 286 | /* |
268 | byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ | 287 | * byte 3: . . by8 bx8 . . . . |
288 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | ||
289 | */ | ||
269 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; | 290 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; |
270 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 291 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
271 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); | 292 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); |
272 | /* For compatibility with the X Synaptics driver scale up one | 293 | /* |
273 | coordinate and report as ordinary mouse movent */ | 294 | * For compatibility with the X Synaptics driver scale up |
295 | * one coordinate and report as ordinary mouse movent | ||
296 | */ | ||
274 | input_report_abs(dev, ABS_X, x1 << 2); | 297 | input_report_abs(dev, ABS_X, x1 << 2); |
275 | input_report_abs(dev, ABS_Y, y1 << 2); | 298 | input_report_abs(dev, ABS_Y, y1 << 2); |
276 | /* For compatibility with the proprietary X Elantech driver | 299 | /* |
277 | report both coordinates as hat coordinates */ | 300 | * For compatibility with the proprietary X Elantech driver |
301 | * report both coordinates as hat coordinates | ||
302 | */ | ||
278 | input_report_abs(dev, ABS_HAT0X, x1); | 303 | input_report_abs(dev, ABS_HAT0X, x1); |
279 | input_report_abs(dev, ABS_HAT0Y, y1); | 304 | input_report_abs(dev, ABS_HAT0Y, y1); |
280 | input_report_abs(dev, ABS_HAT1X, x2); | 305 | input_report_abs(dev, ABS_HAT1X, x2); |
@@ -298,7 +323,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) | |||
298 | unsigned char p1, p2, p3; | 323 | unsigned char p1, p2, p3; |
299 | 324 | ||
300 | /* Parity bits are placed differently */ | 325 | /* Parity bits are placed differently */ |
301 | if (etd->fw_version_maj == 0x01) { | 326 | if (etd->fw_version < 0x020000) { |
302 | /* byte 0: D U p1 p2 1 p3 R L */ | 327 | /* byte 0: D U p1 p2 1 p3 R L */ |
303 | p1 = (packet[0] & 0x20) >> 5; | 328 | p1 = (packet[0] & 0x20) >> 5; |
304 | p2 = (packet[0] & 0x10) >> 4; | 329 | p2 = (packet[0] & 0x10) >> 4; |
@@ -390,23 +415,21 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
390 | if (rc == 0) | 415 | if (rc == 0) |
391 | break; | 416 | break; |
392 | tries--; | 417 | tries--; |
393 | elantech_debug("elantech.c: retrying read (%d).\n", | 418 | elantech_debug("retrying read (%d).\n", tries); |
394 | tries); | ||
395 | msleep(ETP_READ_BACK_DELAY); | 419 | msleep(ETP_READ_BACK_DELAY); |
396 | } while (tries > 0); | 420 | } while (tries > 0); |
397 | 421 | ||
398 | if (rc) { | 422 | if (rc) { |
399 | pr_err("elantech.c: failed to read back register 0x10.\n"); | 423 | pr_err("failed to read back register 0x10.\n"); |
400 | } else if (etd->hw_version == 1 && | 424 | } else if (etd->hw_version == 1 && |
401 | !(val & ETP_R10_ABSOLUTE_MODE)) { | 425 | !(val & ETP_R10_ABSOLUTE_MODE)) { |
402 | pr_err("elantech.c: touchpad refuses " | 426 | pr_err("touchpad refuses to switch to absolute mode.\n"); |
403 | "to switch to absolute mode.\n"); | ||
404 | rc = -1; | 427 | rc = -1; |
405 | } | 428 | } |
406 | } | 429 | } |
407 | 430 | ||
408 | if (rc) | 431 | if (rc) |
409 | pr_err("elantech.c: failed to initialise registers.\n"); | 432 | pr_err("failed to initialise registers.\n"); |
410 | 433 | ||
411 | return rc; | 434 | return rc; |
412 | } | 435 | } |
@@ -434,7 +457,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
434 | switch (etd->hw_version) { | 457 | switch (etd->hw_version) { |
435 | case 1: | 458 | case 1: |
436 | /* Rocker button */ | 459 | /* Rocker button */ |
437 | if ((etd->fw_version_maj == 0x01) && | 460 | if (etd->fw_version < 0x020000 && |
438 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 461 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
439 | __set_bit(BTN_FORWARD, dev->keybit); | 462 | __set_bit(BTN_FORWARD, dev->keybit); |
440 | __set_bit(BTN_BACK, dev->keybit); | 463 | __set_bit(BTN_BACK, dev->keybit); |
@@ -552,6 +575,24 @@ static struct attribute_group elantech_attr_group = { | |||
552 | .attrs = elantech_attrs, | 575 | .attrs = elantech_attrs, |
553 | }; | 576 | }; |
554 | 577 | ||
578 | static bool elantech_is_signature_valid(const unsigned char *param) | ||
579 | { | ||
580 | static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10 }; | ||
581 | int i; | ||
582 | |||
583 | if (param[0] == 0) | ||
584 | return false; | ||
585 | |||
586 | if (param[1] == 0) | ||
587 | return true; | ||
588 | |||
589 | for (i = 0; i < ARRAY_SIZE(rates); i++) | ||
590 | if (param[2] == rates[i]) | ||
591 | return false; | ||
592 | |||
593 | return true; | ||
594 | } | ||
595 | |||
555 | /* | 596 | /* |
556 | * Use magic knock to detect Elantech touchpad | 597 | * Use magic knock to detect Elantech touchpad |
557 | */ | 598 | */ |
@@ -567,7 +608,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
567 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 608 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
568 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || | 609 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || |
569 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | 610 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { |
570 | pr_debug("elantech.c: sending Elantech magic knock failed.\n"); | 611 | pr_debug("sending Elantech magic knock failed.\n"); |
571 | return -1; | 612 | return -1; |
572 | } | 613 | } |
573 | 614 | ||
@@ -576,8 +617,7 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
576 | * set of magic numbers | 617 | * set of magic numbers |
577 | */ | 618 | */ |
578 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { | 619 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { |
579 | pr_debug("elantech.c: " | 620 | pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", |
580 | "unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | ||
581 | param[0], param[1], param[2]); | 621 | param[0], param[1], param[2]); |
582 | return -1; | 622 | return -1; |
583 | } | 623 | } |
@@ -588,16 +628,20 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
588 | * to Elantech magic knock and there might be more. | 628 | * to Elantech magic knock and there might be more. |
589 | */ | 629 | */ |
590 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 630 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
591 | pr_debug("elantech.c: failed to query firmware version.\n"); | 631 | pr_debug("failed to query firmware version.\n"); |
592 | return -1; | 632 | return -1; |
593 | } | 633 | } |
594 | 634 | ||
595 | pr_debug("elantech.c: Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", | 635 | pr_debug("Elantech version query result 0x%02x, 0x%02x, 0x%02x.\n", |
596 | param[0], param[1], param[2]); | 636 | param[0], param[1], param[2]); |
597 | 637 | ||
598 | if (param[0] == 0 || param[1] != 0) { | 638 | if (!elantech_is_signature_valid(param)) { |
599 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | 639 | if (!force_elantech) { |
600 | return -1; | 640 | pr_debug("Probably not a real Elantech touchpad. Aborting.\n"); |
641 | return -1; | ||
642 | } | ||
643 | |||
644 | pr_debug("Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); | ||
601 | } | 645 | } |
602 | 646 | ||
603 | if (set_properties) { | 647 | if (set_properties) { |
@@ -628,7 +672,7 @@ static int elantech_reconnect(struct psmouse *psmouse) | |||
628 | return -1; | 672 | return -1; |
629 | 673 | ||
630 | if (elantech_set_absolute_mode(psmouse)) { | 674 | if (elantech_set_absolute_mode(psmouse)) { |
631 | pr_err("elantech.c: failed to put touchpad back into absolute mode.\n"); | 675 | pr_err("failed to put touchpad back into absolute mode.\n"); |
632 | return -1; | 676 | return -1; |
633 | } | 677 | } |
634 | 678 | ||
@@ -656,17 +700,17 @@ int elantech_init(struct psmouse *psmouse) | |||
656 | * Do the version query again so we can store the result | 700 | * Do the version query again so we can store the result |
657 | */ | 701 | */ |
658 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { | 702 | if (synaptics_send_cmd(psmouse, ETP_FW_VERSION_QUERY, param)) { |
659 | pr_err("elantech.c: failed to query firmware version.\n"); | 703 | pr_err("failed to query firmware version.\n"); |
660 | goto init_fail; | 704 | goto init_fail; |
661 | } | 705 | } |
662 | etd->fw_version_maj = param[0]; | 706 | |
663 | etd->fw_version_min = param[2]; | 707 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
664 | 708 | ||
665 | /* | 709 | /* |
666 | * Assume every version greater than this is new EeePC style | 710 | * Assume every version greater than this is new EeePC style |
667 | * hardware with 6 byte packets | 711 | * hardware with 6 byte packets |
668 | */ | 712 | */ |
669 | if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { | 713 | if (etd->fw_version >= 0x020030) { |
670 | etd->hw_version = 2; | 714 | etd->hw_version = 2; |
671 | /* For now show extra debug information */ | 715 | /* For now show extra debug information */ |
672 | etd->debug = 1; | 716 | etd->debug = 1; |
@@ -676,14 +720,15 @@ int elantech_init(struct psmouse *psmouse) | |||
676 | etd->hw_version = 1; | 720 | etd->hw_version = 1; |
677 | etd->paritycheck = 1; | 721 | etd->paritycheck = 1; |
678 | } | 722 | } |
679 | pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", | 723 | |
680 | etd->hw_version, etd->fw_version_maj, etd->fw_version_min); | 724 | pr_info("assuming hardware version %d, firmware version %d.%d.%d\n", |
725 | etd->hw_version, param[0], param[1], param[2]); | ||
681 | 726 | ||
682 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { | 727 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { |
683 | pr_err("elantech.c: failed to query capabilities.\n"); | 728 | pr_err("failed to query capabilities.\n"); |
684 | goto init_fail; | 729 | goto init_fail; |
685 | } | 730 | } |
686 | pr_info("elantech.c: Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", | 731 | pr_info("Synaptics capabilities query result 0x%02x, 0x%02x, 0x%02x.\n", |
687 | param[0], param[1], param[2]); | 732 | param[0], param[1], param[2]); |
688 | etd->capabilities = param[0]; | 733 | etd->capabilities = param[0]; |
689 | 734 | ||
@@ -692,14 +737,13 @@ int elantech_init(struct psmouse *psmouse) | |||
692 | * a touch action starts causing the mouse cursor or scrolled page | 737 | * a touch action starts causing the mouse cursor or scrolled page |
693 | * to jump. Enable a workaround. | 738 | * to jump. Enable a workaround. |
694 | */ | 739 | */ |
695 | if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { | 740 | if (etd->fw_version == 0x020022) { |
696 | pr_info("elantech.c: firmware version 2.34 detected, " | 741 | pr_info("firmware version 2.0.34 detected, enabling jumpy cursor workaround\n"); |
697 | "enabling jumpy cursor workaround\n"); | ||
698 | etd->jumpy_cursor = 1; | 742 | etd->jumpy_cursor = 1; |
699 | } | 743 | } |
700 | 744 | ||
701 | if (elantech_set_absolute_mode(psmouse)) { | 745 | if (elantech_set_absolute_mode(psmouse)) { |
702 | pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); | 746 | pr_err("failed to put touchpad into absolute mode.\n"); |
703 | goto init_fail; | 747 | goto init_fail; |
704 | } | 748 | } |
705 | 749 | ||
@@ -708,8 +752,7 @@ int elantech_init(struct psmouse *psmouse) | |||
708 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | 752 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, |
709 | &elantech_attr_group); | 753 | &elantech_attr_group); |
710 | if (error) { | 754 | if (error) { |
711 | pr_err("elantech.c: failed to create sysfs attributes, error: %d.\n", | 755 | pr_err("failed to create sysfs attributes, error: %d.\n", error); |
712 | error); | ||
713 | goto init_fail; | 756 | goto init_fail; |
714 | } | 757 | } |
715 | 758 | ||
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index feac5f7af96..ac57bde1bb9 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -100,11 +100,10 @@ struct elantech_data { | |||
100 | unsigned char reg_26; | 100 | unsigned char reg_26; |
101 | unsigned char debug; | 101 | unsigned char debug; |
102 | unsigned char capabilities; | 102 | unsigned char capabilities; |
103 | unsigned char fw_version_maj; | ||
104 | unsigned char fw_version_min; | ||
105 | unsigned char hw_version; | ||
106 | unsigned char paritycheck; | 103 | unsigned char paritycheck; |
107 | unsigned char jumpy_cursor; | 104 | unsigned char jumpy_cursor; |
105 | unsigned char hw_version; | ||
106 | unsigned int fw_version; | ||
108 | unsigned char parity[256]; | 107 | unsigned char parity[256]; |
109 | }; | 108 | }; |
110 | 109 | ||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 08d66d820d2..1d2205b2480 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #include "psmouse.h" | 40 | #include "psmouse.h" |
41 | #include "hgpk.h" | 41 | #include "hgpk.h" |
42 | 42 | ||
43 | static int tpdebug; | 43 | static bool tpdebug; |
44 | module_param(tpdebug, int, 0644); | 44 | module_param(tpdebug, bool, 0644); |
45 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); | 45 | MODULE_PARM_DESC(tpdebug, "enable debugging, dumping packets to KERN_DEBUG."); |
46 | 46 | ||
47 | static int recalib_delta = 100; | 47 | static int recalib_delta = 100; |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 543c240a85f..c9983aee908 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -56,36 +56,36 @@ static psmouse_ret_t ps2pp_process_byte(struct psmouse *psmouse) | |||
56 | /* Logitech extended packet */ | 56 | /* Logitech extended packet */ |
57 | switch ((packet[1] >> 4) | (packet[0] & 0x30)) { | 57 | switch ((packet[1] >> 4) | (packet[0] & 0x30)) { |
58 | 58 | ||
59 | case 0x0d: /* Mouse extra info */ | 59 | case 0x0d: /* Mouse extra info */ |
60 | 60 | ||
61 | input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL, | 61 | input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL, |
62 | (int) (packet[2] & 8) - (int) (packet[2] & 7)); | 62 | (int) (packet[2] & 8) - (int) (packet[2] & 7)); |
63 | input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1); | 63 | input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1); |
64 | input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1); | 64 | input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1); |
65 | 65 | ||
66 | break; | 66 | break; |
67 | 67 | ||
68 | case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */ | 68 | case 0x0e: /* buttons 4, 5, 6, 7, 8, 9, 10 info */ |
69 | 69 | ||
70 | input_report_key(dev, BTN_SIDE, (packet[2]) & 1); | 70 | input_report_key(dev, BTN_SIDE, (packet[2]) & 1); |
71 | input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1); | 71 | input_report_key(dev, BTN_EXTRA, (packet[2] >> 1) & 1); |
72 | input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1); | 72 | input_report_key(dev, BTN_BACK, (packet[2] >> 3) & 1); |
73 | input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1); | 73 | input_report_key(dev, BTN_FORWARD, (packet[2] >> 4) & 1); |
74 | input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1); | 74 | input_report_key(dev, BTN_TASK, (packet[2] >> 2) & 1); |
75 | 75 | ||
76 | break; | 76 | break; |
77 | 77 | ||
78 | case 0x0f: /* TouchPad extra info */ | 78 | case 0x0f: /* TouchPad extra info */ |
79 | 79 | ||
80 | input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL, | 80 | input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL, |
81 | (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); | 81 | (int) ((packet[2] >> 4) & 8) - (int) ((packet[2] >> 4) & 7)); |
82 | packet[0] = packet[2] | 0x08; | 82 | packet[0] = packet[2] | 0x08; |
83 | break; | 83 | break; |
84 | 84 | ||
85 | #ifdef DEBUG | 85 | #ifdef DEBUG |
86 | default: | 86 | default: |
87 | printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n", | 87 | printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n", |
88 | (packet[1] >> 4) | (packet[0] & 0x30)); | 88 | (packet[1] >> 4) | (packet[0] & 0x30)); |
89 | #endif | 89 | #endif |
90 | } | 90 | } |
91 | } else { | 91 | } else { |
@@ -250,7 +250,6 @@ static const struct ps2pp_info *get_model_info(unsigned char model) | |||
250 | if (model == ps2pp_list[i].model) | 250 | if (model == ps2pp_list[i].model) |
251 | return &ps2pp_list[i]; | 251 | return &ps2pp_list[i]; |
252 | 252 | ||
253 | printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model); | ||
254 | return NULL; | 253 | return NULL; |
255 | } | 254 | } |
256 | 255 | ||
@@ -285,31 +284,32 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, | |||
285 | __set_bit(REL_HWHEEL, input_dev->relbit); | 284 | __set_bit(REL_HWHEEL, input_dev->relbit); |
286 | 285 | ||
287 | switch (model_info->kind) { | 286 | switch (model_info->kind) { |
288 | case PS2PP_KIND_WHEEL: | ||
289 | psmouse->name = "Wheel Mouse"; | ||
290 | break; | ||
291 | |||
292 | case PS2PP_KIND_MX: | ||
293 | psmouse->name = "MX Mouse"; | ||
294 | break; | ||
295 | 287 | ||
296 | case PS2PP_KIND_TP3: | 288 | case PS2PP_KIND_WHEEL: |
297 | psmouse->name = "TouchPad 3"; | 289 | psmouse->name = "Wheel Mouse"; |
298 | break; | 290 | break; |
299 | 291 | ||
300 | case PS2PP_KIND_TRACKMAN: | 292 | case PS2PP_KIND_MX: |
301 | psmouse->name = "TrackMan"; | 293 | psmouse->name = "MX Mouse"; |
302 | break; | 294 | break; |
303 | 295 | ||
304 | default: | 296 | case PS2PP_KIND_TP3: |
305 | /* | 297 | psmouse->name = "TouchPad 3"; |
306 | * Set name to "Mouse" only when using PS2++, | 298 | break; |
307 | * otherwise let other protocols define suitable | 299 | |
308 | * name | 300 | case PS2PP_KIND_TRACKMAN: |
309 | */ | 301 | psmouse->name = "TrackMan"; |
310 | if (using_ps2pp) | 302 | break; |
311 | psmouse->name = "Mouse"; | 303 | |
312 | break; | 304 | default: |
305 | /* | ||
306 | * Set name to "Mouse" only when using PS2++, | ||
307 | * otherwise let other protocols define suitable | ||
308 | * name | ||
309 | */ | ||
310 | if (using_ps2pp) | ||
311 | psmouse->name = "Mouse"; | ||
312 | break; | ||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
@@ -343,7 +343,8 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) | |||
343 | if (!model || !buttons) | 343 | if (!model || !buttons) |
344 | return -1; | 344 | return -1; |
345 | 345 | ||
346 | if ((model_info = get_model_info(model)) != NULL) { | 346 | model_info = get_model_info(model); |
347 | if (model_info) { | ||
347 | 348 | ||
348 | /* | 349 | /* |
349 | * Do Logitech PS2++ / PS2T++ magic init. | 350 | * Do Logitech PS2++ / PS2T++ magic init. |
@@ -379,6 +380,9 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) | |||
379 | use_ps2pp = true; | 380 | use_ps2pp = true; |
380 | } | 381 | } |
381 | } | 382 | } |
383 | |||
384 | } else { | ||
385 | printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model); | ||
382 | } | 386 | } |
383 | 387 | ||
384 | if (set_properties) { | 388 | if (set_properties) { |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992..979c5021528 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; | |||
110 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
111 | enum psmouse_type type; | 111 | enum psmouse_type type; |
112 | bool maxproto; | 112 | bool maxproto; |
113 | bool ignore_parity; /* Protocol should ignore parity errors from KBC */ | ||
113 | const char *name; | 114 | const char *name; |
114 | const char *alias; | 115 | const char *alias; |
115 | int (*detect)(struct psmouse *, bool); | 116 | int (*detect)(struct psmouse *, bool); |
@@ -146,18 +147,18 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) | |||
146 | 147 | ||
147 | if (psmouse->type == PSMOUSE_IMEX) { | 148 | if (psmouse->type == PSMOUSE_IMEX) { |
148 | switch (packet[3] & 0xC0) { | 149 | switch (packet[3] & 0xC0) { |
149 | case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ | 150 | case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */ |
150 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); | 151 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); |
151 | break; | 152 | break; |
152 | case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ | 153 | case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */ |
153 | input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); | 154 | input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); |
154 | break; | 155 | break; |
155 | case 0x00: | 156 | case 0x00: |
156 | case 0xC0: | 157 | case 0xC0: |
157 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); | 158 | input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); |
158 | input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); | 159 | input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); |
159 | input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); | 160 | input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); |
160 | break; | 161 | break; |
161 | } | 162 | } |
162 | } | 163 | } |
163 | 164 | ||
@@ -246,31 +247,31 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
246 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse); | 247 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse); |
247 | 248 | ||
248 | switch (rc) { | 249 | switch (rc) { |
249 | case PSMOUSE_BAD_DATA: | 250 | case PSMOUSE_BAD_DATA: |
250 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 251 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
251 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 252 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", |
252 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 253 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
253 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { | 254 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
254 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 255 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
255 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 256 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); |
256 | serio_reconnect(psmouse->ps2dev.serio); | 257 | serio_reconnect(psmouse->ps2dev.serio); |
257 | return -1; | 258 | return -1; |
258 | } | ||
259 | } | ||
260 | psmouse->pktcnt = 0; | ||
261 | break; | ||
262 | |||
263 | case PSMOUSE_FULL_PACKET: | ||
264 | psmouse->pktcnt = 0; | ||
265 | if (psmouse->out_of_sync_cnt) { | ||
266 | psmouse->out_of_sync_cnt = 0; | ||
267 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
268 | psmouse->name, psmouse->phys); | ||
269 | } | 259 | } |
270 | break; | 260 | } |
261 | psmouse->pktcnt = 0; | ||
262 | break; | ||
263 | |||
264 | case PSMOUSE_FULL_PACKET: | ||
265 | psmouse->pktcnt = 0; | ||
266 | if (psmouse->out_of_sync_cnt) { | ||
267 | psmouse->out_of_sync_cnt = 0; | ||
268 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
269 | psmouse->name, psmouse->phys); | ||
270 | } | ||
271 | break; | ||
271 | 272 | ||
272 | case PSMOUSE_GOOD_DATA: | 273 | case PSMOUSE_GOOD_DATA: |
273 | break; | 274 | break; |
274 | } | 275 | } |
275 | return 0; | 276 | return 0; |
276 | } | 277 | } |
@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
288 | if (psmouse->state == PSMOUSE_IGNORE) | 289 | if (psmouse->state == PSMOUSE_IGNORE) |
289 | goto out; | 290 | goto out; |
290 | 291 | ||
291 | if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { | 292 | if (unlikely((flags & SERIO_TIMEOUT) || |
293 | ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { | ||
294 | |||
292 | if (psmouse->state == PSMOUSE_ACTIVATED) | 295 | if (psmouse->state == PSMOUSE_ACTIVATED) |
293 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", | 296 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", |
294 | flags & SERIO_TIMEOUT ? " timeout" : "", | 297 | flags & SERIO_TIMEOUT ? " timeout" : "", |
@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
759 | .name = "PS/2", | 762 | .name = "PS/2", |
760 | .alias = "bare", | 763 | .alias = "bare", |
761 | .maxproto = true, | 764 | .maxproto = true, |
765 | .ignore_parity = true, | ||
762 | .detect = ps2bare_detect, | 766 | .detect = ps2bare_detect, |
763 | }, | 767 | }, |
764 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 768 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
786 | .name = "ImPS/2", | 790 | .name = "ImPS/2", |
787 | .alias = "imps", | 791 | .alias = "imps", |
788 | .maxproto = true, | 792 | .maxproto = true, |
793 | .ignore_parity = true, | ||
789 | .detect = intellimouse_detect, | 794 | .detect = intellimouse_detect, |
790 | }, | 795 | }, |
791 | { | 796 | { |
@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
793 | .name = "ImExPS/2", | 798 | .name = "ImExPS/2", |
794 | .alias = "exps", | 799 | .alias = "exps", |
795 | .maxproto = true, | 800 | .maxproto = true, |
801 | .ignore_parity = true, | ||
796 | .detect = im_explorer_detect, | 802 | .detect = im_explorer_detect, |
797 | }, | 803 | }, |
798 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 804 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) | |||
1222 | static int psmouse_switch_protocol(struct psmouse *psmouse, | 1228 | static int psmouse_switch_protocol(struct psmouse *psmouse, |
1223 | const struct psmouse_protocol *proto) | 1229 | const struct psmouse_protocol *proto) |
1224 | { | 1230 | { |
1231 | const struct psmouse_protocol *selected_proto; | ||
1225 | struct input_dev *input_dev = psmouse->dev; | 1232 | struct input_dev *input_dev = psmouse->dev; |
1226 | 1233 | ||
1227 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; | 1234 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
@@ -1238,16 +1245,21 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, | |||
1238 | psmouse->pktsize = 3; | 1245 | psmouse->pktsize = 3; |
1239 | 1246 | ||
1240 | if (proto && (proto->detect || proto->init)) { | 1247 | if (proto && (proto->detect || proto->init)) { |
1241 | if (proto->detect && proto->detect(psmouse, 1) < 0) | 1248 | if (proto->detect && proto->detect(psmouse, true) < 0) |
1242 | return -1; | 1249 | return -1; |
1243 | 1250 | ||
1244 | if (proto->init && proto->init(psmouse) < 0) | 1251 | if (proto->init && proto->init(psmouse) < 0) |
1245 | return -1; | 1252 | return -1; |
1246 | 1253 | ||
1247 | psmouse->type = proto->type; | 1254 | psmouse->type = proto->type; |
1248 | } else | 1255 | selected_proto = proto; |
1256 | } else { | ||
1249 | psmouse->type = psmouse_extensions(psmouse, | 1257 | psmouse->type = psmouse_extensions(psmouse, |
1250 | psmouse_max_proto, true); | 1258 | psmouse_max_proto, true); |
1259 | selected_proto = psmouse_protocol_by_type(psmouse->type); | ||
1260 | } | ||
1261 | |||
1262 | psmouse->ignore_parity = selected_proto->ignore_parity; | ||
1251 | 1263 | ||
1252 | /* | 1264 | /* |
1253 | * If mouse's packet size is 3 there is no point in polling the | 1265 | * If mouse's packet size is 3 there is no point in polling the |
@@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, | |||
1267 | psmouse->resync_time = 0; | 1279 | psmouse->resync_time = 0; |
1268 | 1280 | ||
1269 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", | 1281 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", |
1270 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1282 | selected_proto->name, psmouse->vendor, psmouse->name); |
1271 | 1283 | ||
1272 | input_dev->name = psmouse->devname; | 1284 | input_dev->name = psmouse->devname; |
1273 | input_dev->phys = psmouse->phys; | 1285 | input_dev->phys = psmouse->phys; |
@@ -1382,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio) | |||
1382 | struct psmouse *psmouse = serio_get_drvdata(serio); | 1394 | struct psmouse *psmouse = serio_get_drvdata(serio); |
1383 | struct psmouse *parent = NULL; | 1395 | struct psmouse *parent = NULL; |
1384 | struct serio_driver *drv = serio->drv; | 1396 | struct serio_driver *drv = serio->drv; |
1397 | unsigned char type; | ||
1385 | int rc = -1; | 1398 | int rc = -1; |
1386 | 1399 | ||
1387 | if (!drv || !psmouse) { | 1400 | if (!drv || !psmouse) { |
@@ -1401,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio) | |||
1401 | if (psmouse->reconnect) { | 1414 | if (psmouse->reconnect) { |
1402 | if (psmouse->reconnect(psmouse)) | 1415 | if (psmouse->reconnect(psmouse)) |
1403 | goto out; | 1416 | goto out; |
1404 | } else if (psmouse_probe(psmouse) < 0 || | 1417 | } else { |
1405 | psmouse->type != psmouse_extensions(psmouse, | 1418 | psmouse_reset(psmouse); |
1406 | psmouse_max_proto, false)) { | 1419 | |
1407 | goto out; | 1420 | if (psmouse_probe(psmouse) < 0) |
1421 | goto out; | ||
1422 | |||
1423 | type = psmouse_extensions(psmouse, psmouse_max_proto, false); | ||
1424 | if (psmouse->type != type) | ||
1425 | goto out; | ||
1408 | } | 1426 | } |
1409 | 1427 | ||
1410 | /* ok, the device type (and capabilities) match the old one, | 1428 | /* ok, the device type (and capabilities) match the old one, |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd137f..593e910bfc7 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -47,6 +47,7 @@ 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 | bool ignore_parity; | ||
50 | bool acks_disable_command; | 51 | bool acks_disable_command; |
51 | unsigned int model; | 52 | unsigned int model; |
52 | unsigned long last; | 53 | unsigned long last; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 026df601016..40cea334ad1 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -36,6 +36,8 @@ | |||
36 | * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, | 36 | * The x/y limits are taken from the Synaptics TouchPad interfacing Guide, |
37 | * section 2.3.2, which says that they should be valid regardless of the | 37 | * section 2.3.2, which says that they should be valid regardless of the |
38 | * actual size of the sensor. | 38 | * actual size of the sensor. |
39 | * Note that newer firmware allows querying device for maximum useable | ||
40 | * coordinates. | ||
39 | */ | 41 | */ |
40 | #define XMIN_NOMINAL 1472 | 42 | #define XMIN_NOMINAL 1472 |
41 | #define XMAX_NOMINAL 5472 | 43 | #define XMAX_NOMINAL 5472 |
@@ -137,7 +139,8 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
137 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) | 139 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) |
138 | return -1; | 140 | return -1; |
139 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 141 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
140 | priv->ext_cap = 0; | 142 | priv->ext_cap = priv->ext_cap_0c = 0; |
143 | |||
141 | if (!SYN_CAP_VALID(priv->capabilities)) | 144 | if (!SYN_CAP_VALID(priv->capabilities)) |
142 | return -1; | 145 | return -1; |
143 | 146 | ||
@@ -150,7 +153,7 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
150 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { | 153 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { |
151 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { | 154 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { |
152 | printk(KERN_ERR "Synaptics claims to have extended capabilities," | 155 | printk(KERN_ERR "Synaptics claims to have extended capabilities," |
153 | " but I'm not able to read them."); | 156 | " but I'm not able to read them.\n"); |
154 | } else { | 157 | } else { |
155 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 158 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
156 | 159 | ||
@@ -162,6 +165,16 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
162 | priv->ext_cap &= 0xff0fff; | 165 | priv->ext_cap &= 0xff0fff; |
163 | } | 166 | } |
164 | } | 167 | } |
168 | |||
169 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { | ||
170 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { | ||
171 | printk(KERN_ERR "Synaptics claims to have extended capability 0x0c," | ||
172 | " but I'm not able to read it.\n"); | ||
173 | } else { | ||
174 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | ||
175 | } | ||
176 | } | ||
177 | |||
165 | return 0; | 178 | return 0; |
166 | } | 179 | } |
167 | 180 | ||
@@ -183,23 +196,33 @@ static int synaptics_identify(struct psmouse *psmouse) | |||
183 | } | 196 | } |
184 | 197 | ||
185 | /* | 198 | /* |
186 | * Read touchpad resolution | 199 | * Read touchpad resolution and maximum reported coordinates |
187 | * Resolution is left zero if touchpad does not support the query | 200 | * Resolution is left zero if touchpad does not support the query |
188 | */ | 201 | */ |
189 | static int synaptics_resolution(struct psmouse *psmouse) | 202 | static int synaptics_resolution(struct psmouse *psmouse) |
190 | { | 203 | { |
191 | struct synaptics_data *priv = psmouse->private; | 204 | struct synaptics_data *priv = psmouse->private; |
192 | unsigned char res[3]; | 205 | unsigned char res[3]; |
206 | unsigned char max[3]; | ||
193 | 207 | ||
194 | if (SYN_ID_MAJOR(priv->identity) < 4) | 208 | if (SYN_ID_MAJOR(priv->identity) < 4) |
195 | return 0; | ||
196 | 209 | ||
197 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res)) | 210 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) { |
198 | return 0; | 211 | if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { |
212 | priv->x_res = res[0]; /* x resolution in units/mm */ | ||
213 | priv->y_res = res[2]; /* y resolution in units/mm */ | ||
214 | } | ||
215 | } | ||
199 | 216 | ||
200 | if ((res[0] != 0) && (res[1] & 0x80) && (res[2] != 0)) { | 217 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && |
201 | priv->x_res = res[0]; /* x resolution in units/mm */ | 218 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { |
202 | priv->y_res = res[2]; /* y resolution in units/mm */ | 219 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) { |
220 | printk(KERN_ERR "Synaptics claims to have dimensions query," | ||
221 | " but I'm not able to read it.\n"); | ||
222 | } else { | ||
223 | priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1); | ||
224 | priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3); | ||
225 | } | ||
203 | } | 226 | } |
204 | 227 | ||
205 | return 0; | 228 | return 0; |
@@ -348,7 +371,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
348 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 371 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
349 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 372 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
350 | 373 | ||
351 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 374 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
375 | /* | ||
376 | * Clickpad's button is transmitted as middle button, | ||
377 | * however, since it is primary button, we will report | ||
378 | * it as BTN_LEFT. | ||
379 | */ | ||
380 | hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | ||
381 | |||
382 | } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | ||
352 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | 383 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; |
353 | if (hw->w == 2) | 384 | if (hw->w == 2) |
354 | hw->scroll = (signed char)(buf[1]); | 385 | hw->scroll = (signed char)(buf[1]); |
@@ -501,19 +532,20 @@ static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned cha | |||
501 | return 0; | 532 | return 0; |
502 | 533 | ||
503 | switch (pkt_type) { | 534 | switch (pkt_type) { |
504 | case SYN_NEWABS: | ||
505 | case SYN_NEWABS_RELAXED: | ||
506 | return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; | ||
507 | 535 | ||
508 | case SYN_NEWABS_STRICT: | 536 | case SYN_NEWABS: |
509 | return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; | 537 | case SYN_NEWABS_RELAXED: |
538 | return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx]; | ||
510 | 539 | ||
511 | case SYN_OLDABS: | 540 | case SYN_NEWABS_STRICT: |
512 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; | 541 | return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx]; |
513 | 542 | ||
514 | default: | 543 | case SYN_OLDABS: |
515 | printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type); | 544 | return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx]; |
516 | return 0; | 545 | |
546 | default: | ||
547 | printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type); | ||
548 | return 0; | ||
517 | } | 549 | } |
518 | } | 550 | } |
519 | 551 | ||
@@ -559,8 +591,10 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
559 | int i; | 591 | int i; |
560 | 592 | ||
561 | __set_bit(EV_ABS, dev->evbit); | 593 | __set_bit(EV_ABS, dev->evbit); |
562 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); | 594 | input_set_abs_params(dev, ABS_X, |
563 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); | 595 | XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); |
596 | input_set_abs_params(dev, ABS_Y, | ||
597 | YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); | ||
564 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 598 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
565 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); | 599 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); |
566 | 600 | ||
@@ -593,6 +627,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
593 | 627 | ||
594 | dev->absres[ABS_X] = priv->x_res; | 628 | dev->absres[ABS_X] = priv->x_res; |
595 | dev->absres[ABS_Y] = priv->y_res; | 629 | dev->absres[ABS_Y] = priv->y_res; |
630 | |||
631 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | ||
632 | /* Clickpads report only left button */ | ||
633 | __clear_bit(BTN_RIGHT, dev->keybit); | ||
634 | __clear_bit(BTN_MIDDLE, dev->keybit); | ||
635 | } | ||
596 | } | 636 | } |
597 | 637 | ||
598 | static void synaptics_disconnect(struct psmouse *psmouse) | 638 | static void synaptics_disconnect(struct psmouse *psmouse) |
@@ -697,10 +737,10 @@ int synaptics_init(struct psmouse *psmouse) | |||
697 | 737 | ||
698 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 738 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
699 | 739 | ||
700 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", | 740 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
701 | SYN_ID_MODEL(priv->identity), | 741 | SYN_ID_MODEL(priv->identity), |
702 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), | 742 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), |
703 | priv->model_id, priv->capabilities, priv->ext_cap); | 743 | priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); |
704 | 744 | ||
705 | set_input_params(psmouse->dev, priv); | 745 | set_input_params(psmouse->dev, priv); |
706 | 746 | ||
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index f0f40a331dc..7d4d5e12c0d 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 | 18 | #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 |
19 | #define SYN_QUE_RESOLUTION 0x08 | 19 | #define SYN_QUE_RESOLUTION 0x08 |
20 | #define SYN_QUE_EXT_CAPAB 0x09 | 20 | #define SYN_QUE_EXT_CAPAB 0x09 |
21 | #define SYN_QUE_EXT_CAPAB_0C 0x0c | ||
22 | #define SYN_QUE_EXT_DIMENSIONS 0x0d | ||
21 | 23 | ||
22 | /* synatics modes */ | 24 | /* synatics modes */ |
23 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) | 25 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) |
@@ -48,6 +50,9 @@ | |||
48 | #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) | 50 | #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) |
49 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) | 51 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) |
50 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) | 52 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) |
53 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) | ||
54 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) | ||
55 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) | ||
51 | 56 | ||
52 | /* synaptics modes query bits */ | 57 | /* synaptics modes query bits */ |
53 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 58 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
@@ -96,9 +101,10 @@ struct synaptics_data { | |||
96 | unsigned long int model_id; /* Model-ID */ | 101 | unsigned long int model_id; /* Model-ID */ |
97 | unsigned long int capabilities; /* Capabilities */ | 102 | unsigned long int capabilities; /* Capabilities */ |
98 | unsigned long int ext_cap; /* Extended Capabilities */ | 103 | unsigned long int ext_cap; /* Extended Capabilities */ |
104 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ | ||
99 | unsigned long int identity; /* Identification */ | 105 | unsigned long int identity; /* Identification */ |
100 | int x_res; /* X resolution in units/mm */ | 106 | unsigned int x_res, y_res; /* X/Y resolution in units/mm */ |
101 | int y_res; /* Y resolution in units/mm */ | 107 | unsigned int x_max, y_max; /* Max dimensions (from FW) */ |
102 | 108 | ||
103 | unsigned char pkt_type; /* packet type - old, new, etc */ | 109 | unsigned char pkt_type; /* packet type - old, new, etc */ |
104 | unsigned char mode; /* current mode byte */ | 110 | unsigned char mode; /* current mode byte */ |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 7e319d65ec5..f34f1dbeb57 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -209,4 +209,20 @@ config SERIO_ALTERA_PS2 | |||
209 | To compile this driver as a module, choose M here: the | 209 | To compile this driver as a module, choose M here: the |
210 | module will be called altera_ps2. | 210 | module will be called altera_ps2. |
211 | 211 | ||
212 | config SERIO_AMS_DELTA | ||
213 | tristate "Amstrad Delta (E3) mailboard support" | ||
214 | depends on MACH_AMS_DELTA | ||
215 | default y | ||
216 | select AMS_DELTA_FIQ | ||
217 | ---help--- | ||
218 | Say Y here if you have an E3 and want to use its mailboard, | ||
219 | or any standard AT keyboard connected to the mailboard port. | ||
220 | |||
221 | When used for the E3 mailboard, a non-standard key table | ||
222 | must be loaded from userspace, possibly using udev extras | ||
223 | provided keymap helper utility. | ||
224 | |||
225 | To compile this driver as a module, choose M here; | ||
226 | the module will be called ams_delta_serio. | ||
227 | |||
212 | endif | 228 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index bf945f789d0..84c80bf7185 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
@@ -21,5 +21,6 @@ obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o | |||
21 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o | 21 | obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o |
22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o | 22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o |
23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o | 23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o |
24 | obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o | ||
24 | obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o | 25 | obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o |
25 | obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o | 26 | obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o |
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c new file mode 100644 index 00000000000..8f1770e1e08 --- /dev/null +++ b/drivers/input/serio/ams_delta_serio.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Amstrad E3 (Delta) keyboard port driver | ||
3 | * | ||
4 | * Copyright (c) 2006 Matt Callow | ||
5 | * Copyright (c) 2010 Janusz Krzysztofik | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * Thanks to Cliff Lawson for his help | ||
12 | * | ||
13 | * The Amstrad Delta keyboard (aka mailboard) uses normal PC-AT style serial | ||
14 | * transmission. The keyboard port is formed of two GPIO lines, for clock | ||
15 | * and data. Due to strict timing requirements of the interface, | ||
16 | * the serial data stream is read and processed by a FIQ handler. | ||
17 | * The resulting words are fetched by this driver from a circular buffer. | ||
18 | * | ||
19 | * Standard AT keyboard driver (atkbd) is used for handling the keyboard data. | ||
20 | * However, when used with the E3 mailboard that producecs non-standard | ||
21 | * scancodes, a custom key table must be prepared and loaded from userspace. | ||
22 | */ | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/serio.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #include <asm/mach-types.h> | ||
29 | #include <plat/board-ams-delta.h> | ||
30 | |||
31 | #include <mach/ams-delta-fiq.h> | ||
32 | |||
33 | MODULE_AUTHOR("Matt Callow"); | ||
34 | MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | static struct serio *ams_delta_serio; | ||
38 | |||
39 | static int check_data(int data) | ||
40 | { | ||
41 | int i, parity = 0; | ||
42 | |||
43 | /* check valid stop bit */ | ||
44 | if (!(data & 0x400)) { | ||
45 | dev_warn(&ams_delta_serio->dev, | ||
46 | "invalid stop bit, data=0x%X\n", | ||
47 | data); | ||
48 | return SERIO_FRAME; | ||
49 | } | ||
50 | /* calculate the parity */ | ||
51 | for (i = 1; i < 10; i++) { | ||
52 | if (data & (1 << i)) | ||
53 | parity++; | ||
54 | } | ||
55 | /* it should be odd */ | ||
56 | if (!(parity & 0x01)) { | ||
57 | dev_warn(&ams_delta_serio->dev, | ||
58 | "paritiy check failed, data=0x%X parity=0x%X\n", | ||
59 | data, parity); | ||
60 | return SERIO_PARITY; | ||
61 | } | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id) | ||
66 | { | ||
67 | int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF]; | ||
68 | int data, dfl; | ||
69 | u8 scancode; | ||
70 | |||
71 | fiq_buffer[FIQ_IRQ_PEND] = 0; | ||
72 | |||
73 | /* | ||
74 | * Read data from the circular buffer, check it | ||
75 | * and then pass it on the serio | ||
76 | */ | ||
77 | while (fiq_buffer[FIQ_KEYS_CNT] > 0) { | ||
78 | |||
79 | data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++]; | ||
80 | fiq_buffer[FIQ_KEYS_CNT]--; | ||
81 | if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN]) | ||
82 | fiq_buffer[FIQ_HEAD_OFFSET] = 0; | ||
83 | |||
84 | dfl = check_data(data); | ||
85 | scancode = (u8) (data >> 1) & 0xFF; | ||
86 | serio_interrupt(ams_delta_serio, scancode, dfl); | ||
87 | } | ||
88 | return IRQ_HANDLED; | ||
89 | } | ||
90 | |||
91 | static int ams_delta_serio_open(struct serio *serio) | ||
92 | { | ||
93 | /* enable keyboard */ | ||
94 | ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, | ||
95 | AMD_DELTA_LATCH2_KEYBRD_PWR); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void ams_delta_serio_close(struct serio *serio) | ||
101 | { | ||
102 | /* disable keyboard */ | ||
103 | ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, 0); | ||
104 | } | ||
105 | |||
106 | static int __init ams_delta_serio_init(void) | ||
107 | { | ||
108 | int err; | ||
109 | |||
110 | if (!machine_is_ams_delta()) | ||
111 | return -ENODEV; | ||
112 | |||
113 | ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
114 | if (!ams_delta_serio) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | ams_delta_serio->id.type = SERIO_8042; | ||
118 | ams_delta_serio->open = ams_delta_serio_open; | ||
119 | ams_delta_serio->close = ams_delta_serio_close; | ||
120 | strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter", | ||
121 | sizeof(ams_delta_serio->name)); | ||
122 | strlcpy(ams_delta_serio->phys, "GPIO/serio0", | ||
123 | sizeof(ams_delta_serio->phys)); | ||
124 | |||
125 | err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_DATA, "serio-data"); | ||
126 | if (err) { | ||
127 | pr_err("ams_delta_serio: Couldn't request gpio pin for data\n"); | ||
128 | goto serio; | ||
129 | } | ||
130 | gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); | ||
131 | |||
132 | err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_CLK, "serio-clock"); | ||
133 | if (err) { | ||
134 | pr_err("ams_delta_serio: couldn't request gpio pin for clock\n"); | ||
135 | goto gpio_data; | ||
136 | } | ||
137 | gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); | ||
138 | |||
139 | err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), | ||
140 | ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING, | ||
141 | "ams-delta-serio", 0); | ||
142 | if (err < 0) { | ||
143 | pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n", | ||
144 | gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); | ||
145 | goto gpio_clk; | ||
146 | } | ||
147 | /* | ||
148 | * Since GPIO register handling for keyboard clock pin is performed | ||
149 | * at FIQ level, switch back from edge to simple interrupt handler | ||
150 | * to avoid bad interaction. | ||
151 | */ | ||
152 | set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), | ||
153 | handle_simple_irq); | ||
154 | |||
155 | serio_register_port(ams_delta_serio); | ||
156 | dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name); | ||
157 | |||
158 | return 0; | ||
159 | gpio_clk: | ||
160 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); | ||
161 | gpio_data: | ||
162 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); | ||
163 | serio: | ||
164 | kfree(ams_delta_serio); | ||
165 | return err; | ||
166 | } | ||
167 | module_init(ams_delta_serio_init); | ||
168 | |||
169 | static void __exit ams_delta_serio_exit(void) | ||
170 | { | ||
171 | serio_unregister_port(ams_delta_serio); | ||
172 | free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); | ||
173 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); | ||
174 | gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); | ||
175 | kfree(ams_delta_serio); | ||
176 | } | ||
177 | module_exit(ams_delta_serio_exit); | ||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index ead0494721d..6168469ad1a 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -660,8 +660,21 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * | |||
660 | } | 660 | } |
661 | 661 | ||
662 | static struct pnp_device_id pnp_kbd_devids[] = { | 662 | static struct pnp_device_id pnp_kbd_devids[] = { |
663 | { .id = "PNP0300", .driver_data = 0 }, | ||
664 | { .id = "PNP0301", .driver_data = 0 }, | ||
665 | { .id = "PNP0302", .driver_data = 0 }, | ||
663 | { .id = "PNP0303", .driver_data = 0 }, | 666 | { .id = "PNP0303", .driver_data = 0 }, |
667 | { .id = "PNP0304", .driver_data = 0 }, | ||
668 | { .id = "PNP0305", .driver_data = 0 }, | ||
669 | { .id = "PNP0306", .driver_data = 0 }, | ||
670 | { .id = "PNP0309", .driver_data = 0 }, | ||
671 | { .id = "PNP030a", .driver_data = 0 }, | ||
664 | { .id = "PNP030b", .driver_data = 0 }, | 672 | { .id = "PNP030b", .driver_data = 0 }, |
673 | { .id = "PNP0320", .driver_data = 0 }, | ||
674 | { .id = "PNP0343", .driver_data = 0 }, | ||
675 | { .id = "PNP0344", .driver_data = 0 }, | ||
676 | { .id = "PNP0345", .driver_data = 0 }, | ||
677 | { .id = "CPQA0D7", .driver_data = 0 }, | ||
665 | { .id = "", }, | 678 | { .id = "", }, |
666 | }; | 679 | }; |
667 | 680 | ||
@@ -672,6 +685,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = { | |||
672 | }; | 685 | }; |
673 | 686 | ||
674 | static struct pnp_device_id pnp_aux_devids[] = { | 687 | static struct pnp_device_id pnp_aux_devids[] = { |
688 | { .id = "AUI0200", .driver_data = 0 }, | ||
675 | { .id = "FJC6000", .driver_data = 0 }, | 689 | { .id = "FJC6000", .driver_data = 0 }, |
676 | { .id = "FJC6001", .driver_data = 0 }, | 690 | { .id = "FJC6001", .driver_data = 0 }, |
677 | { .id = "PNP0f03", .driver_data = 0 }, | 691 | { .id = "PNP0f03", .driver_data = 0 }, |
diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index 670c61c5a51..aea9a9399a3 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c | |||
@@ -66,18 +66,18 @@ static void usb_acecad_irq(struct urb *urb) | |||
66 | int prox, status; | 66 | int prox, status; |
67 | 67 | ||
68 | switch (urb->status) { | 68 | switch (urb->status) { |
69 | case 0: | 69 | case 0: |
70 | /* success */ | 70 | /* success */ |
71 | break; | 71 | break; |
72 | case -ECONNRESET: | 72 | case -ECONNRESET: |
73 | case -ENOENT: | 73 | case -ENOENT: |
74 | case -ESHUTDOWN: | 74 | case -ESHUTDOWN: |
75 | /* this urb is terminated, clean up */ | 75 | /* this urb is terminated, clean up */ |
76 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); | 76 | dbg("%s - urb shutting down with status: %d", __func__, urb->status); |
77 | return; | 77 | return; |
78 | default: | 78 | default: |
79 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); | 79 | dbg("%s - nonzero urb status received: %d", __func__, urb->status); |
80 | goto resubmit; | 80 | goto resubmit; |
81 | } | 81 | } |
82 | 82 | ||
83 | prox = (data[0] & 0x04) >> 2; | 83 | prox = (data[0] & 0x04) >> 2; |
@@ -135,7 +135,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
135 | struct usb_acecad *acecad; | 135 | struct usb_acecad *acecad; |
136 | struct input_dev *input_dev; | 136 | struct input_dev *input_dev; |
137 | int pipe, maxp; | 137 | int pipe, maxp; |
138 | int err = -ENOMEM; | 138 | int err; |
139 | 139 | ||
140 | if (interface->desc.bNumEndpoints != 1) | 140 | if (interface->desc.bNumEndpoints != 1) |
141 | return -ENODEV; | 141 | return -ENODEV; |
@@ -155,7 +155,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
155 | goto fail1; | 155 | goto fail1; |
156 | } | 156 | } |
157 | 157 | ||
158 | acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); | 158 | acecad->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &acecad->data_dma); |
159 | if (!acecad->data) { | 159 | if (!acecad->data) { |
160 | err= -ENOMEM; | 160 | err= -ENOMEM; |
161 | goto fail1; | 161 | goto fail1; |
@@ -193,40 +193,34 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
193 | input_dev->close = usb_acecad_close; | 193 | input_dev->close = usb_acecad_close; |
194 | 194 | ||
195 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 195 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
196 | input_dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | | ||
197 | BIT_MASK(ABS_PRESSURE); | ||
198 | input_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | | ||
199 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | ||
200 | input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) | | 196 | input_dev->keybit[BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_TOOL_PEN) | |
201 | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) | | 197 | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS) | |
202 | BIT_MASK(BTN_STYLUS2); | 198 | BIT_MASK(BTN_STYLUS2); |
203 | 199 | ||
204 | switch (id->driver_info) { | 200 | switch (id->driver_info) { |
205 | case 0: | 201 | case 0: |
206 | input_dev->absmax[ABS_X] = 5000; | 202 | input_set_abs_params(input_dev, ABS_X, 0, 5000, 4, 0); |
207 | input_dev->absmax[ABS_Y] = 3750; | 203 | input_set_abs_params(input_dev, ABS_Y, 0, 3750, 4, 0); |
208 | input_dev->absmax[ABS_PRESSURE] = 512; | 204 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 512, 0, 0); |
209 | if (!strlen(acecad->name)) | 205 | if (!strlen(acecad->name)) |
210 | snprintf(acecad->name, sizeof(acecad->name), | 206 | snprintf(acecad->name, sizeof(acecad->name), |
211 | "USB Acecad Flair Tablet %04x:%04x", | 207 | "USB Acecad Flair Tablet %04x:%04x", |
212 | le16_to_cpu(dev->descriptor.idVendor), | 208 | le16_to_cpu(dev->descriptor.idVendor), |
213 | le16_to_cpu(dev->descriptor.idProduct)); | 209 | le16_to_cpu(dev->descriptor.idProduct)); |
214 | break; | 210 | break; |
215 | case 1: | 211 | |
216 | input_dev->absmax[ABS_X] = 3000; | 212 | case 1: |
217 | input_dev->absmax[ABS_Y] = 2250; | 213 | input_set_abs_params(input_dev, ABS_X, 0, 53000, 4, 0); |
218 | input_dev->absmax[ABS_PRESSURE] = 1024; | 214 | input_set_abs_params(input_dev, ABS_Y, 0, 2250, 4, 0); |
219 | if (!strlen(acecad->name)) | 215 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1024, 0, 0); |
220 | snprintf(acecad->name, sizeof(acecad->name), | 216 | if (!strlen(acecad->name)) |
221 | "USB Acecad 302 Tablet %04x:%04x", | 217 | snprintf(acecad->name, sizeof(acecad->name), |
222 | le16_to_cpu(dev->descriptor.idVendor), | 218 | "USB Acecad 302 Tablet %04x:%04x", |
223 | le16_to_cpu(dev->descriptor.idProduct)); | 219 | le16_to_cpu(dev->descriptor.idVendor), |
224 | break; | 220 | le16_to_cpu(dev->descriptor.idProduct)); |
221 | break; | ||
225 | } | 222 | } |
226 | 223 | ||
227 | input_dev->absfuzz[ABS_X] = 4; | ||
228 | input_dev->absfuzz[ABS_Y] = 4; | ||
229 | |||
230 | usb_fill_int_urb(acecad->irq, dev, pipe, | 224 | usb_fill_int_urb(acecad->irq, dev, pipe, |
231 | acecad->data, maxp > 8 ? 8 : maxp, | 225 | acecad->data, maxp > 8 ? 8 : maxp, |
232 | usb_acecad_irq, acecad, endpoint->bInterval); | 226 | usb_acecad_irq, acecad, endpoint->bInterval); |
@@ -241,7 +235,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
241 | 235 | ||
242 | return 0; | 236 | return 0; |
243 | 237 | ||
244 | fail2: usb_buffer_free(dev, 8, acecad->data, acecad->data_dma); | 238 | fail2: usb_free_coherent(dev, 8, acecad->data, acecad->data_dma); |
245 | fail1: input_free_device(input_dev); | 239 | fail1: input_free_device(input_dev); |
246 | kfree(acecad); | 240 | kfree(acecad); |
247 | return err; | 241 | return err; |
@@ -252,13 +246,11 @@ static void usb_acecad_disconnect(struct usb_interface *intf) | |||
252 | struct usb_acecad *acecad = usb_get_intfdata(intf); | 246 | struct usb_acecad *acecad = usb_get_intfdata(intf); |
253 | 247 | ||
254 | usb_set_intfdata(intf, NULL); | 248 | usb_set_intfdata(intf, NULL); |
255 | if (acecad) { | 249 | |
256 | usb_kill_urb(acecad->irq); | 250 | input_unregister_device(acecad->input); |
257 | input_unregister_device(acecad->input); | 251 | usb_free_urb(acecad->irq); |
258 | usb_free_urb(acecad->irq); | 252 | usb_free_coherent(acecad->usbdev, 8, acecad->data, acecad->data_dma); |
259 | usb_buffer_free(interface_to_usbdev(intf), 10, acecad->data, acecad->data_dma); | 253 | kfree(acecad); |
260 | kfree(acecad); | ||
261 | } | ||
262 | } | 254 | } |
263 | 255 | ||
264 | static struct usb_device_id usb_acecad_id_table [] = { | 256 | static struct usb_device_id usb_acecad_id_table [] = { |
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 4be039d7dca..51b80b08d46 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
@@ -1711,8 +1711,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1711 | goto fail1; | 1711 | goto fail1; |
1712 | } | 1712 | } |
1713 | 1713 | ||
1714 | aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, | 1714 | aiptek->data = usb_alloc_coherent(usbdev, AIPTEK_PACKET_LENGTH, |
1715 | GFP_ATOMIC, &aiptek->data_dma); | 1715 | GFP_ATOMIC, &aiptek->data_dma); |
1716 | if (!aiptek->data) { | 1716 | if (!aiptek->data) { |
1717 | dev_warn(&intf->dev, "cannot allocate usb buffer\n"); | 1717 | dev_warn(&intf->dev, "cannot allocate usb buffer\n"); |
1718 | goto fail1; | 1718 | goto fail1; |
@@ -1884,8 +1884,8 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1884 | 1884 | ||
1885 | fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); | 1885 | fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); |
1886 | fail3: usb_free_urb(aiptek->urb); | 1886 | fail3: usb_free_urb(aiptek->urb); |
1887 | fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, | 1887 | fail2: usb_free_coherent(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data, |
1888 | aiptek->data_dma); | 1888 | aiptek->data_dma); |
1889 | fail1: usb_set_intfdata(intf, NULL); | 1889 | fail1: usb_set_intfdata(intf, NULL); |
1890 | input_free_device(inputdev); | 1890 | input_free_device(inputdev); |
1891 | kfree(aiptek); | 1891 | kfree(aiptek); |
@@ -1909,9 +1909,9 @@ static void aiptek_disconnect(struct usb_interface *intf) | |||
1909 | input_unregister_device(aiptek->inputdev); | 1909 | input_unregister_device(aiptek->inputdev); |
1910 | sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); | 1910 | sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); |
1911 | usb_free_urb(aiptek->urb); | 1911 | usb_free_urb(aiptek->urb); |
1912 | usb_buffer_free(interface_to_usbdev(intf), | 1912 | usb_free_coherent(interface_to_usbdev(intf), |
1913 | AIPTEK_PACKET_LENGTH, | 1913 | AIPTEK_PACKET_LENGTH, |
1914 | aiptek->data, aiptek->data_dma); | 1914 | aiptek->data, aiptek->data_dma); |
1915 | kfree(aiptek); | 1915 | kfree(aiptek); |
1916 | } | 1916 | } |
1917 | } | 1917 | } |
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 866a9ee1af1..8ea6afe2e99 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c | |||
@@ -850,8 +850,8 @@ static int gtco_probe(struct usb_interface *usbinterface, | |||
850 | gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); | 850 | gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface)); |
851 | 851 | ||
852 | /* Allocate some data for incoming reports */ | 852 | /* Allocate some data for incoming reports */ |
853 | gtco->buffer = usb_buffer_alloc(gtco->usbdev, REPORT_MAX_SIZE, | 853 | gtco->buffer = usb_alloc_coherent(gtco->usbdev, REPORT_MAX_SIZE, |
854 | GFP_KERNEL, >co->buf_dma); | 854 | GFP_KERNEL, >co->buf_dma); |
855 | if (!gtco->buffer) { | 855 | if (!gtco->buffer) { |
856 | err("No more memory for us buffers"); | 856 | err("No more memory for us buffers"); |
857 | error = -ENOMEM; | 857 | error = -ENOMEM; |
@@ -982,8 +982,8 @@ static int gtco_probe(struct usb_interface *usbinterface, | |||
982 | err_free_urb: | 982 | err_free_urb: |
983 | usb_free_urb(gtco->urbinfo); | 983 | usb_free_urb(gtco->urbinfo); |
984 | err_free_buf: | 984 | err_free_buf: |
985 | usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, | 985 | usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, |
986 | gtco->buffer, gtco->buf_dma); | 986 | gtco->buffer, gtco->buf_dma); |
987 | err_free_devs: | 987 | err_free_devs: |
988 | input_free_device(input_dev); | 988 | input_free_device(input_dev); |
989 | kfree(gtco); | 989 | kfree(gtco); |
@@ -1005,8 +1005,8 @@ static void gtco_disconnect(struct usb_interface *interface) | |||
1005 | input_unregister_device(gtco->inputdevice); | 1005 | input_unregister_device(gtco->inputdevice); |
1006 | usb_kill_urb(gtco->urbinfo); | 1006 | usb_kill_urb(gtco->urbinfo); |
1007 | usb_free_urb(gtco->urbinfo); | 1007 | usb_free_urb(gtco->urbinfo); |
1008 | usb_buffer_free(gtco->usbdev, REPORT_MAX_SIZE, | 1008 | usb_free_coherent(gtco->usbdev, REPORT_MAX_SIZE, |
1009 | gtco->buffer, gtco->buf_dma); | 1009 | gtco->buffer, gtco->buf_dma); |
1010 | kfree(gtco); | 1010 | kfree(gtco); |
1011 | } | 1011 | } |
1012 | 1012 | ||
diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 6682b17bf84..290f4e57b58 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c | |||
@@ -34,10 +34,6 @@ struct kbtab { | |||
34 | struct input_dev *dev; | 34 | struct input_dev *dev; |
35 | struct usb_device *usbdev; | 35 | struct usb_device *usbdev; |
36 | struct urb *irq; | 36 | struct urb *irq; |
37 | int x, y; | ||
38 | int button; | ||
39 | int pressure; | ||
40 | __u32 serial[2]; | ||
41 | char phys[32]; | 37 | char phys[32]; |
42 | }; | 38 | }; |
43 | 39 | ||
@@ -46,6 +42,7 @@ static void kbtab_irq(struct urb *urb) | |||
46 | struct kbtab *kbtab = urb->context; | 42 | struct kbtab *kbtab = urb->context; |
47 | unsigned char *data = kbtab->data; | 43 | unsigned char *data = kbtab->data; |
48 | struct input_dev *dev = kbtab->dev; | 44 | struct input_dev *dev = kbtab->dev; |
45 | int pressure; | ||
49 | int retval; | 46 | int retval; |
50 | 47 | ||
51 | switch (urb->status) { | 48 | switch (urb->status) { |
@@ -63,31 +60,27 @@ static void kbtab_irq(struct urb *urb) | |||
63 | goto exit; | 60 | goto exit; |
64 | } | 61 | } |
65 | 62 | ||
66 | kbtab->x = get_unaligned_le16(&data[1]); | ||
67 | kbtab->y = get_unaligned_le16(&data[3]); | ||
68 | |||
69 | kbtab->pressure = (data[5]); | ||
70 | 63 | ||
71 | input_report_key(dev, BTN_TOOL_PEN, 1); | 64 | input_report_key(dev, BTN_TOOL_PEN, 1); |
72 | 65 | ||
73 | input_report_abs(dev, ABS_X, kbtab->x); | 66 | input_report_abs(dev, ABS_X, get_unaligned_le16(&data[1])); |
74 | input_report_abs(dev, ABS_Y, kbtab->y); | 67 | input_report_abs(dev, ABS_Y, get_unaligned_le16(&data[3])); |
75 | 68 | ||
76 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | 69 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ |
77 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | 70 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); |
78 | 71 | ||
79 | if (-1 == kb_pressure_click) { | 72 | pressure = data[5]; |
80 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | 73 | if (kb_pressure_click == -1) |
81 | } else { | 74 | input_report_abs(dev, ABS_PRESSURE, pressure); |
82 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | 75 | else |
83 | }; | 76 | input_report_key(dev, BTN_LEFT, pressure > kb_pressure_click ? 1 : 0); |
84 | 77 | ||
85 | input_sync(dev); | 78 | input_sync(dev); |
86 | 79 | ||
87 | exit: | 80 | exit: |
88 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 81 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
89 | if (retval) | 82 | if (retval) |
90 | err ("%s - usb_submit_urb failed with result %d", | 83 | err("%s - usb_submit_urb failed with result %d", |
91 | __func__, retval); | 84 | __func__, retval); |
92 | } | 85 | } |
93 | 86 | ||
@@ -129,7 +122,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
129 | if (!kbtab || !input_dev) | 122 | if (!kbtab || !input_dev) |
130 | goto fail1; | 123 | goto fail1; |
131 | 124 | ||
132 | kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma); | 125 | kbtab->data = usb_alloc_coherent(dev, 8, GFP_KERNEL, &kbtab->data_dma); |
133 | if (!kbtab->data) | 126 | if (!kbtab->data) |
134 | goto fail1; | 127 | goto fail1; |
135 | 128 | ||
@@ -153,13 +146,11 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
153 | input_dev->open = kbtab_open; | 146 | input_dev->open = kbtab_open; |
154 | input_dev->close = kbtab_close; | 147 | input_dev->close = kbtab_close; |
155 | 148 | ||
156 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | | 149 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
157 | BIT_MASK(EV_MSC); | 150 | input_dev->keybit[BIT_WORD(BTN_LEFT)] |= |
158 | input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 151 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
159 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | 152 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= |
160 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | | 153 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_TOUCH); |
161 | BIT_MASK(BTN_TOUCH); | ||
162 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
163 | input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); | 154 | input_set_abs_params(input_dev, ABS_X, 0, 0x2000, 4, 0); |
164 | input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); | 155 | input_set_abs_params(input_dev, ABS_Y, 0, 0x1750, 4, 0); |
165 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); | 156 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xff, 0, 0); |
@@ -182,7 +173,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
182 | return 0; | 173 | return 0; |
183 | 174 | ||
184 | fail3: usb_free_urb(kbtab->irq); | 175 | fail3: usb_free_urb(kbtab->irq); |
185 | fail2: usb_buffer_free(dev, 10, kbtab->data, kbtab->data_dma); | 176 | fail2: usb_free_coherent(dev, 8, kbtab->data, kbtab->data_dma); |
186 | fail1: input_free_device(input_dev); | 177 | fail1: input_free_device(input_dev); |
187 | kfree(kbtab); | 178 | kfree(kbtab); |
188 | return error; | 179 | return error; |
@@ -193,13 +184,11 @@ static void kbtab_disconnect(struct usb_interface *intf) | |||
193 | struct kbtab *kbtab = usb_get_intfdata(intf); | 184 | struct kbtab *kbtab = usb_get_intfdata(intf); |
194 | 185 | ||
195 | usb_set_intfdata(intf, NULL); | 186 | usb_set_intfdata(intf, NULL); |
196 | if (kbtab) { | 187 | |
197 | usb_kill_urb(kbtab->irq); | 188 | input_unregister_device(kbtab->dev); |
198 | input_unregister_device(kbtab->dev); | 189 | usb_free_urb(kbtab->irq); |
199 | usb_free_urb(kbtab->irq); | 190 | usb_free_coherent(kbtab->usbdev, 8, kbtab->data, kbtab->data_dma); |
200 | usb_buffer_free(interface_to_usbdev(intf), 10, kbtab->data, kbtab->data_dma); | 191 | kfree(kbtab); |
201 | kfree(kbtab); | ||
202 | } | ||
203 | } | 192 | } |
204 | 193 | ||
205 | static struct usb_driver kbtab_driver = { | 194 | static struct usb_driver kbtab_driver = { |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 8fef1b689c6..284dfaab6b8 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -106,44 +106,18 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
106 | 106 | ||
107 | struct wacom { | 107 | struct wacom { |
108 | dma_addr_t data_dma; | 108 | dma_addr_t data_dma; |
109 | struct input_dev *dev; | ||
110 | struct usb_device *usbdev; | 109 | struct usb_device *usbdev; |
111 | struct usb_interface *intf; | 110 | struct usb_interface *intf; |
112 | struct urb *irq; | 111 | struct urb *irq; |
113 | struct wacom_wac *wacom_wac; | 112 | struct wacom_wac wacom_wac; |
114 | struct mutex lock; | 113 | struct mutex lock; |
115 | unsigned int open:1; | 114 | bool open; |
116 | char phys[32]; | 115 | char phys[32]; |
117 | }; | 116 | }; |
118 | 117 | ||
119 | struct wacom_combo { | ||
120 | struct wacom *wacom; | ||
121 | struct urb *urb; | ||
122 | }; | ||
123 | |||
124 | extern const struct usb_device_id wacom_ids[]; | 118 | extern const struct usb_device_id wacom_ids[]; |
125 | 119 | ||
126 | extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); | 120 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); |
127 | extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); | 121 | void wacom_setup_input_capabilities(struct input_dev *input_dev, |
128 | extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); | 122 | struct wacom_wac *wacom_wac); |
129 | extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); | ||
130 | extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value); | ||
131 | extern void wacom_input_sync(void *wcombo); | ||
132 | extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
133 | extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
134 | extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
135 | extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
136 | extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
137 | extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
138 | extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
139 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
140 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
141 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
142 | extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
143 | extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
144 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
145 | extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
146 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | ||
147 | extern __u16 wacom_be16_to_cpu(unsigned char *data); | ||
148 | |||
149 | #endif | 123 | #endif |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f46502589e4..2dc0c07c046 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -11,8 +11,8 @@ | |||
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include "wacom.h" | ||
15 | #include "wacom_wac.h" | 14 | #include "wacom_wac.h" |
15 | #include "wacom.h" | ||
16 | 16 | ||
17 | /* defines to get HID report descriptor */ | 17 | /* defines to get HID report descriptor */ |
18 | #define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) | 18 | #define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) |
@@ -70,15 +70,9 @@ static int usb_set_report(struct usb_interface *intf, unsigned char type, | |||
70 | buf, size, 1000); | 70 | buf, size, 1000); |
71 | } | 71 | } |
72 | 72 | ||
73 | static struct input_dev * get_input_dev(struct wacom_combo *wcombo) | ||
74 | { | ||
75 | return wcombo->wacom->dev; | ||
76 | } | ||
77 | |||
78 | static void wacom_sys_irq(struct urb *urb) | 73 | static void wacom_sys_irq(struct urb *urb) |
79 | { | 74 | { |
80 | struct wacom *wacom = urb->context; | 75 | struct wacom *wacom = urb->context; |
81 | struct wacom_combo wcombo; | ||
82 | int retval; | 76 | int retval; |
83 | 77 | ||
84 | switch (urb->status) { | 78 | switch (urb->status) { |
@@ -96,59 +90,16 @@ static void wacom_sys_irq(struct urb *urb) | |||
96 | goto exit; | 90 | goto exit; |
97 | } | 91 | } |
98 | 92 | ||
99 | wcombo.wacom = wacom; | 93 | wacom_wac_irq(&wacom->wacom_wac, urb->actual_length); |
100 | wcombo.urb = urb; | ||
101 | |||
102 | if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo)) | ||
103 | input_sync(get_input_dev(&wcombo)); | ||
104 | 94 | ||
105 | exit: | 95 | exit: |
106 | usb_mark_last_busy(wacom->usbdev); | 96 | usb_mark_last_busy(wacom->usbdev); |
107 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 97 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
108 | if (retval) | 98 | if (retval) |
109 | err ("%s - usb_submit_urb failed with result %d", | 99 | err ("%s - usb_submit_urb failed with result %d", |
110 | __func__, retval); | 100 | __func__, retval); |
111 | } | 101 | } |
112 | 102 | ||
113 | void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) | ||
114 | { | ||
115 | input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); | ||
116 | } | ||
117 | |||
118 | void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) | ||
119 | { | ||
120 | input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); | ||
121 | } | ||
122 | |||
123 | void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) | ||
124 | { | ||
125 | input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); | ||
126 | } | ||
127 | |||
128 | void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) | ||
129 | { | ||
130 | input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); | ||
131 | } | ||
132 | |||
133 | __u16 wacom_be16_to_cpu(unsigned char *data) | ||
134 | { | ||
135 | __u16 value; | ||
136 | value = be16_to_cpu(*(__be16 *) data); | ||
137 | return value; | ||
138 | } | ||
139 | |||
140 | __u16 wacom_le16_to_cpu(unsigned char *data) | ||
141 | { | ||
142 | __u16 value; | ||
143 | value = le16_to_cpu(*(__le16 *) data); | ||
144 | return value; | ||
145 | } | ||
146 | |||
147 | void wacom_input_sync(void *wcombo) | ||
148 | { | ||
149 | input_sync(get_input_dev((struct wacom_combo *)wcombo)); | ||
150 | } | ||
151 | |||
152 | static int wacom_open(struct input_dev *dev) | 103 | static int wacom_open(struct input_dev *dev) |
153 | { | 104 | { |
154 | struct wacom *wacom = input_get_drvdata(dev); | 105 | struct wacom *wacom = input_get_drvdata(dev); |
@@ -168,7 +119,7 @@ static int wacom_open(struct input_dev *dev) | |||
168 | return -EIO; | 119 | return -EIO; |
169 | } | 120 | } |
170 | 121 | ||
171 | wacom->open = 1; | 122 | wacom->open = true; |
172 | wacom->intf->needs_remote_wakeup = 1; | 123 | wacom->intf->needs_remote_wakeup = 1; |
173 | 124 | ||
174 | mutex_unlock(&wacom->lock); | 125 | mutex_unlock(&wacom->lock); |
@@ -181,128 +132,11 @@ static void wacom_close(struct input_dev *dev) | |||
181 | 132 | ||
182 | mutex_lock(&wacom->lock); | 133 | mutex_lock(&wacom->lock); |
183 | usb_kill_urb(wacom->irq); | 134 | usb_kill_urb(wacom->irq); |
184 | wacom->open = 0; | 135 | wacom->open = false; |
185 | wacom->intf->needs_remote_wakeup = 0; | 136 | wacom->intf->needs_remote_wakeup = 0; |
186 | mutex_unlock(&wacom->lock); | 137 | mutex_unlock(&wacom->lock); |
187 | } | 138 | } |
188 | 139 | ||
189 | void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
190 | { | ||
191 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) | | ||
192 | BIT_MASK(BTN_5); | ||
193 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); | ||
194 | } | ||
195 | |||
196 | void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
197 | { | ||
198 | input_dev->evbit[0] |= BIT_MASK(EV_MSC); | ||
199 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
200 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); | ||
201 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | | ||
202 | BIT_MASK(BTN_4); | ||
203 | } | ||
204 | |||
205 | void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
206 | { | ||
207 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
208 | input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); | ||
209 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | | ||
210 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | ||
211 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | ||
212 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
213 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); | ||
214 | input_set_abs_params(input_dev, ABS_DISTANCE, | ||
215 | 0, wacom_wac->features.distance_max, 0, 0); | ||
216 | } | ||
217 | |||
218 | void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
219 | { | ||
220 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); | ||
221 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | | ||
222 | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); | ||
223 | input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); | ||
224 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
225 | } | ||
226 | |||
227 | void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
228 | { | ||
229 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | | ||
230 | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7); | ||
231 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); | ||
232 | } | ||
233 | |||
234 | void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
235 | { | ||
236 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); | ||
237 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); | ||
238 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6); | ||
239 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
240 | } | ||
241 | |||
242 | void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
243 | { | ||
244 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_7) | BIT_MASK(BTN_8); | ||
245 | } | ||
246 | |||
247 | void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
248 | { | ||
249 | input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); | ||
250 | } | ||
251 | |||
252 | void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
253 | { | ||
254 | input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL); | ||
255 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
256 | input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); | ||
257 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | | ||
258 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | | ||
259 | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); | ||
260 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | ||
261 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
262 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | | ||
263 | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | | ||
264 | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); | ||
265 | input_set_abs_params(input_dev, ABS_DISTANCE, | ||
266 | 0, wacom_wac->features.distance_max, 0, 0); | ||
267 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
268 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
269 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
270 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
271 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
272 | } | ||
273 | |||
274 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
275 | { | ||
276 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | | ||
277 | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); | ||
278 | } | ||
279 | |||
280 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
281 | { | ||
282 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); | ||
283 | } | ||
284 | |||
285 | void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
286 | { | ||
287 | struct wacom_features *features = &wacom_wac->features; | ||
288 | |||
289 | if (features->device_type == BTN_TOOL_DOUBLETAP || | ||
290 | features->device_type == BTN_TOOL_TRIPLETAP) { | ||
291 | input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); | ||
292 | input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); | ||
293 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
298 | { | ||
299 | if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { | ||
300 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); | ||
301 | input_dev->evbit[0] |= BIT_MASK(EV_MSC); | ||
302 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, | 140 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, |
307 | struct wacom_features *features) | 141 | struct wacom_features *features) |
308 | { | 142 | { |
@@ -362,9 +196,9 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
362 | features->device_type = BTN_TOOL_TRIPLETAP; | 196 | features->device_type = BTN_TOOL_TRIPLETAP; |
363 | } | 197 | } |
364 | features->x_max = | 198 | features->x_max = |
365 | wacom_le16_to_cpu(&report[i + 3]); | 199 | get_unaligned_le16(&report[i + 3]); |
366 | features->x_phy = | 200 | features->x_phy = |
367 | wacom_le16_to_cpu(&report[i + 6]); | 201 | get_unaligned_le16(&report[i + 6]); |
368 | features->unit = report[i + 9]; | 202 | features->unit = report[i + 9]; |
369 | features->unitExpo = report[i + 11]; | 203 | features->unitExpo = report[i + 11]; |
370 | i += 12; | 204 | i += 12; |
@@ -374,7 +208,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
374 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 208 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
375 | features->device_type = BTN_TOOL_PEN; | 209 | features->device_type = BTN_TOOL_PEN; |
376 | features->x_max = | 210 | features->x_max = |
377 | wacom_le16_to_cpu(&report[i + 3]); | 211 | get_unaligned_le16(&report[i + 3]); |
378 | i += 4; | 212 | i += 4; |
379 | } | 213 | } |
380 | } else if (usage == WCM_DIGITIZER) { | 214 | } else if (usage == WCM_DIGITIZER) { |
@@ -396,15 +230,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
396 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 230 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
397 | features->device_type = BTN_TOOL_TRIPLETAP; | 231 | features->device_type = BTN_TOOL_TRIPLETAP; |
398 | features->y_max = | 232 | features->y_max = |
399 | wacom_le16_to_cpu(&report[i + 3]); | 233 | get_unaligned_le16(&report[i + 3]); |
400 | features->y_phy = | 234 | features->y_phy = |
401 | wacom_le16_to_cpu(&report[i + 6]); | 235 | get_unaligned_le16(&report[i + 6]); |
402 | i += 7; | 236 | i += 7; |
403 | } else { | 237 | } else { |
404 | features->y_max = | 238 | features->y_max = |
405 | features->x_max; | 239 | features->x_max; |
406 | features->y_phy = | 240 | features->y_phy = |
407 | wacom_le16_to_cpu(&report[i + 3]); | 241 | get_unaligned_le16(&report[i + 3]); |
408 | i += 4; | 242 | i += 4; |
409 | } | 243 | } |
410 | } else if (pen) { | 244 | } else if (pen) { |
@@ -413,7 +247,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
413 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | 247 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; |
414 | features->device_type = BTN_TOOL_PEN; | 248 | features->device_type = BTN_TOOL_PEN; |
415 | features->y_max = | 249 | features->y_max = |
416 | wacom_le16_to_cpu(&report[i + 3]); | 250 | get_unaligned_le16(&report[i + 3]); |
417 | i += 4; | 251 | i += 4; |
418 | } | 252 | } |
419 | } | 253 | } |
@@ -432,7 +266,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
432 | case HID_USAGE_UNDEFINED: | 266 | case HID_USAGE_UNDEFINED: |
433 | if (usage == WCM_DESKTOP && finger) /* capacity */ | 267 | if (usage == WCM_DESKTOP && finger) /* capacity */ |
434 | features->pressure_max = | 268 | features->pressure_max = |
435 | wacom_le16_to_cpu(&report[i + 3]); | 269 | get_unaligned_le16(&report[i + 3]); |
436 | i += 4; | 270 | i += 4; |
437 | break; | 271 | break; |
438 | } | 272 | } |
@@ -528,6 +362,81 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
528 | return error; | 362 | return error; |
529 | } | 363 | } |
530 | 364 | ||
365 | struct wacom_usbdev_data { | ||
366 | struct list_head list; | ||
367 | struct kref kref; | ||
368 | struct usb_device *dev; | ||
369 | struct wacom_shared shared; | ||
370 | }; | ||
371 | |||
372 | static LIST_HEAD(wacom_udev_list); | ||
373 | static DEFINE_MUTEX(wacom_udev_list_lock); | ||
374 | |||
375 | static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) | ||
376 | { | ||
377 | struct wacom_usbdev_data *data; | ||
378 | |||
379 | list_for_each_entry(data, &wacom_udev_list, list) { | ||
380 | if (data->dev == dev) { | ||
381 | kref_get(&data->kref); | ||
382 | return data; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | return NULL; | ||
387 | } | ||
388 | |||
389 | static int wacom_add_shared_data(struct wacom_wac *wacom, | ||
390 | struct usb_device *dev) | ||
391 | { | ||
392 | struct wacom_usbdev_data *data; | ||
393 | int retval = 0; | ||
394 | |||
395 | mutex_lock(&wacom_udev_list_lock); | ||
396 | |||
397 | data = wacom_get_usbdev_data(dev); | ||
398 | if (!data) { | ||
399 | data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL); | ||
400 | if (!data) { | ||
401 | retval = -ENOMEM; | ||
402 | goto out; | ||
403 | } | ||
404 | |||
405 | kref_init(&data->kref); | ||
406 | data->dev = dev; | ||
407 | list_add_tail(&data->list, &wacom_udev_list); | ||
408 | } | ||
409 | |||
410 | wacom->shared = &data->shared; | ||
411 | |||
412 | out: | ||
413 | mutex_unlock(&wacom_udev_list_lock); | ||
414 | return retval; | ||
415 | } | ||
416 | |||
417 | static void wacom_release_shared_data(struct kref *kref) | ||
418 | { | ||
419 | struct wacom_usbdev_data *data = | ||
420 | container_of(kref, struct wacom_usbdev_data, kref); | ||
421 | |||
422 | mutex_lock(&wacom_udev_list_lock); | ||
423 | list_del(&data->list); | ||
424 | mutex_unlock(&wacom_udev_list_lock); | ||
425 | |||
426 | kfree(data); | ||
427 | } | ||
428 | |||
429 | static void wacom_remove_shared_data(struct wacom_wac *wacom) | ||
430 | { | ||
431 | struct wacom_usbdev_data *data; | ||
432 | |||
433 | if (wacom->shared) { | ||
434 | data = container_of(wacom->shared, struct wacom_usbdev_data, shared); | ||
435 | kref_put(&data->kref, wacom_release_shared_data); | ||
436 | wacom->shared = NULL; | ||
437 | } | ||
438 | } | ||
439 | |||
531 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 440 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
532 | { | 441 | { |
533 | struct usb_device *dev = interface_to_usbdev(intf); | 442 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -542,13 +451,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
542 | return -EINVAL; | 451 | return -EINVAL; |
543 | 452 | ||
544 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | 453 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); |
545 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | ||
546 | input_dev = input_allocate_device(); | 454 | input_dev = input_allocate_device(); |
547 | if (!wacom || !input_dev || !wacom_wac) { | 455 | if (!wacom || !input_dev) { |
548 | error = -ENOMEM; | 456 | error = -ENOMEM; |
549 | goto fail1; | 457 | goto fail1; |
550 | } | 458 | } |
551 | 459 | ||
460 | wacom_wac = &wacom->wacom_wac; | ||
552 | wacom_wac->features = *((struct wacom_features *)id->driver_info); | 461 | wacom_wac->features = *((struct wacom_features *)id->driver_info); |
553 | features = &wacom_wac->features; | 462 | features = &wacom_wac->features; |
554 | if (features->pktlen > WACOM_PKGLEN_MAX) { | 463 | if (features->pktlen > WACOM_PKGLEN_MAX) { |
@@ -556,8 +465,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
556 | goto fail1; | 465 | goto fail1; |
557 | } | 466 | } |
558 | 467 | ||
559 | wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, | 468 | wacom_wac->data = usb_alloc_coherent(dev, WACOM_PKGLEN_MAX, |
560 | GFP_KERNEL, &wacom->data_dma); | 469 | GFP_KERNEL, &wacom->data_dma); |
561 | if (!wacom_wac->data) { | 470 | if (!wacom_wac->data) { |
562 | error = -ENOMEM; | 471 | error = -ENOMEM; |
563 | goto fail1; | 472 | goto fail1; |
@@ -570,20 +479,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
570 | } | 479 | } |
571 | 480 | ||
572 | wacom->usbdev = dev; | 481 | wacom->usbdev = dev; |
573 | wacom->dev = input_dev; | ||
574 | wacom->intf = intf; | 482 | wacom->intf = intf; |
575 | mutex_init(&wacom->lock); | 483 | mutex_init(&wacom->lock); |
576 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | 484 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); |
577 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | 485 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); |
578 | 486 | ||
579 | usb_to_input_id(dev, &input_dev->id); | 487 | wacom_wac->input = input_dev; |
580 | |||
581 | input_dev->dev.parent = &intf->dev; | ||
582 | |||
583 | input_set_drvdata(input_dev, wacom); | ||
584 | |||
585 | input_dev->open = wacom_open; | ||
586 | input_dev->close = wacom_close; | ||
587 | 488 | ||
588 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 489 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
589 | 490 | ||
@@ -600,20 +501,21 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
600 | features->device_type == BTN_TOOL_PEN ? | 501 | features->device_type == BTN_TOOL_PEN ? |
601 | " Pen" : " Finger", | 502 | " Pen" : " Finger", |
602 | sizeof(wacom_wac->name)); | 503 | sizeof(wacom_wac->name)); |
504 | |||
505 | error = wacom_add_shared_data(wacom_wac, dev); | ||
506 | if (error) | ||
507 | goto fail3; | ||
603 | } | 508 | } |
604 | 509 | ||
605 | input_dev->name = wacom_wac->name; | 510 | input_dev->name = wacom_wac->name; |
606 | wacom->wacom_wac = wacom_wac; | 511 | input_dev->name = wacom_wac->name; |
607 | 512 | input_dev->dev.parent = &intf->dev; | |
608 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 513 | input_dev->open = wacom_open; |
609 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); | 514 | input_dev->close = wacom_close; |
610 | 515 | usb_to_input_id(dev, &input_dev->id); | |
611 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); | 516 | input_set_drvdata(input_dev, wacom); |
612 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); | ||
613 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); | ||
614 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); | ||
615 | 517 | ||
616 | wacom_init_input_dev(input_dev, wacom_wac); | 518 | wacom_setup_input_capabilities(input_dev, wacom_wac); |
617 | 519 | ||
618 | usb_fill_int_urb(wacom->irq, dev, | 520 | usb_fill_int_urb(wacom->irq, dev, |
619 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | 521 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), |
@@ -622,9 +524,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
622 | wacom->irq->transfer_dma = wacom->data_dma; | 524 | wacom->irq->transfer_dma = wacom->data_dma; |
623 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 525 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
624 | 526 | ||
625 | error = input_register_device(wacom->dev); | 527 | error = input_register_device(input_dev); |
626 | if (error) | 528 | if (error) |
627 | goto fail3; | 529 | goto fail4; |
628 | 530 | ||
629 | /* Note that if query fails it is not a hard failure */ | 531 | /* Note that if query fails it is not a hard failure */ |
630 | wacom_query_tablet_data(intf, features); | 532 | wacom_query_tablet_data(intf, features); |
@@ -632,11 +534,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
632 | usb_set_intfdata(intf, wacom); | 534 | usb_set_intfdata(intf, wacom); |
633 | return 0; | 535 | return 0; |
634 | 536 | ||
537 | fail4: wacom_remove_shared_data(wacom_wac); | ||
635 | fail3: usb_free_urb(wacom->irq); | 538 | fail3: usb_free_urb(wacom->irq); |
636 | fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); | 539 | fail2: usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
637 | fail1: input_free_device(input_dev); | 540 | fail1: input_free_device(input_dev); |
638 | kfree(wacom); | 541 | kfree(wacom); |
639 | kfree(wacom_wac); | ||
640 | return error; | 542 | return error; |
641 | } | 543 | } |
642 | 544 | ||
@@ -647,11 +549,11 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
647 | usb_set_intfdata(intf, NULL); | 549 | usb_set_intfdata(intf, NULL); |
648 | 550 | ||
649 | usb_kill_urb(wacom->irq); | 551 | usb_kill_urb(wacom->irq); |
650 | input_unregister_device(wacom->dev); | 552 | input_unregister_device(wacom->wacom_wac.input); |
651 | usb_free_urb(wacom->irq); | 553 | usb_free_urb(wacom->irq); |
652 | usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, | 554 | usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
653 | wacom->wacom_wac->data, wacom->data_dma); | 555 | wacom->wacom_wac.data, wacom->data_dma); |
654 | kfree(wacom->wacom_wac); | 556 | wacom_remove_shared_data(&wacom->wacom_wac); |
655 | kfree(wacom); | 557 | kfree(wacom); |
656 | } | 558 | } |
657 | 559 | ||
@@ -669,7 +571,7 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) | |||
669 | static int wacom_resume(struct usb_interface *intf) | 571 | static int wacom_resume(struct usb_interface *intf) |
670 | { | 572 | { |
671 | struct wacom *wacom = usb_get_intfdata(intf); | 573 | struct wacom *wacom = usb_get_intfdata(intf); |
672 | struct wacom_features *features = &wacom->wacom_wac->features; | 574 | struct wacom_features *features = &wacom->wacom_wac.features; |
673 | int rv; | 575 | int rv; |
674 | 576 | ||
675 | mutex_lock(&wacom->lock); | 577 | mutex_lock(&wacom->lock); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 4a852d815c6..847fd0135bc 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -11,52 +11,58 @@ | |||
11 | * the Free Software Foundation; either version 2 of the License, or | 11 | * the Free Software Foundation; either version 2 of the License, or |
12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
13 | */ | 13 | */ |
14 | #include "wacom.h" | 14 | |
15 | #include "wacom_wac.h" | 15 | #include "wacom_wac.h" |
16 | #include "wacom.h" | ||
16 | 17 | ||
17 | static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) | 18 | static int wacom_penpartner_irq(struct wacom_wac *wacom) |
18 | { | 19 | { |
19 | unsigned char *data = wacom->data; | 20 | unsigned char *data = wacom->data; |
21 | struct input_dev *input = wacom->input; | ||
20 | 22 | ||
21 | switch (data[0]) { | 23 | switch (data[0]) { |
22 | case 1: | 24 | case 1: |
23 | if (data[5] & 0x80) { | 25 | if (data[5] & 0x80) { |
24 | wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 26 | wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
25 | wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; | 27 | wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID; |
26 | wacom_report_key(wcombo, wacom->tool[0], 1); | 28 | input_report_key(input, wacom->tool[0], 1); |
27 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 29 | input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ |
28 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 30 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); |
29 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 31 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); |
30 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | 32 | input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); |
31 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127)); | 33 | input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -127)); |
32 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | 34 | input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); |
33 | } else { | 35 | } else { |
34 | wacom_report_key(wcombo, wacom->tool[0], 0); | 36 | input_report_key(input, wacom->tool[0], 0); |
35 | wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */ | 37 | input_report_abs(input, ABS_MISC, 0); /* report tool id */ |
36 | wacom_report_abs(wcombo, ABS_PRESSURE, -1); | 38 | input_report_abs(input, ABS_PRESSURE, -1); |
37 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 39 | input_report_key(input, BTN_TOUCH, 0); |
38 | } | 40 | } |
39 | break; | 41 | break; |
40 | case 2: | 42 | |
41 | wacom_report_key(wcombo, BTN_TOOL_PEN, 1); | 43 | case 2: |
42 | wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ | 44 | input_report_key(input, BTN_TOOL_PEN, 1); |
43 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 45 | input_report_abs(input, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */ |
44 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 46 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); |
45 | wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127); | 47 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); |
46 | wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); | 48 | input_report_abs(input, ABS_PRESSURE, (signed char)data[6] + 127); |
47 | wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40)); | 49 | input_report_key(input, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); |
48 | break; | 50 | input_report_key(input, BTN_STYLUS, (data[5] & 0x40)); |
49 | default: | 51 | break; |
50 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | 52 | |
51 | return 0; | 53 | default: |
54 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | ||
55 | return 0; | ||
52 | } | 56 | } |
57 | |||
53 | return 1; | 58 | return 1; |
54 | } | 59 | } |
55 | 60 | ||
56 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | 61 | static int wacom_pl_irq(struct wacom_wac *wacom) |
57 | { | 62 | { |
58 | struct wacom_features *features = &wacom->features; | 63 | struct wacom_features *features = &wacom->features; |
59 | unsigned char *data = wacom->data; | 64 | unsigned char *data = wacom->data; |
65 | struct input_dev *input = wacom->input; | ||
60 | int prox, pressure; | 66 | int prox, pressure; |
61 | 67 | ||
62 | if (data[0] != WACOM_REPORT_PENABLED) { | 68 | if (data[0] != WACOM_REPORT_PENABLED) { |
@@ -90,8 +96,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | |||
90 | /* was entered with stylus2 pressed */ | 96 | /* was entered with stylus2 pressed */ |
91 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { | 97 | if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) { |
92 | /* report out proximity for previous tool */ | 98 | /* report out proximity for previous tool */ |
93 | wacom_report_key(wcombo, wacom->tool[1], 0); | 99 | input_report_key(input, wacom->tool[1], 0); |
94 | wacom_input_sync(wcombo); | 100 | input_sync(input); |
95 | wacom->tool[1] = BTN_TOOL_PEN; | 101 | wacom->tool[1] = BTN_TOOL_PEN; |
96 | return 0; | 102 | return 0; |
97 | } | 103 | } |
@@ -101,32 +107,33 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | |||
101 | wacom->tool[1] = BTN_TOOL_PEN; | 107 | wacom->tool[1] = BTN_TOOL_PEN; |
102 | wacom->id[0] = STYLUS_DEVICE_ID; | 108 | wacom->id[0] = STYLUS_DEVICE_ID; |
103 | } | 109 | } |
104 | wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */ | 110 | input_report_key(input, wacom->tool[1], prox); /* report in proximity for tool */ |
105 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 111 | input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ |
106 | wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); | 112 | input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14)); |
107 | wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); | 113 | input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14)); |
108 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 114 | input_report_abs(input, ABS_PRESSURE, pressure); |
109 | 115 | ||
110 | wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08); | 116 | input_report_key(input, BTN_TOUCH, data[4] & 0x08); |
111 | wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10); | 117 | input_report_key(input, BTN_STYLUS, data[4] & 0x10); |
112 | /* Only allow the stylus2 button to be reported for the pen tool. */ | 118 | /* Only allow the stylus2 button to be reported for the pen tool. */ |
113 | wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); | 119 | input_report_key(input, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20)); |
114 | } else { | 120 | } else { |
115 | /* report proximity-out of a (valid) tool */ | 121 | /* report proximity-out of a (valid) tool */ |
116 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | 122 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { |
117 | /* Unknown tool selected default to pen tool */ | 123 | /* Unknown tool selected default to pen tool */ |
118 | wacom->tool[1] = BTN_TOOL_PEN; | 124 | wacom->tool[1] = BTN_TOOL_PEN; |
119 | } | 125 | } |
120 | wacom_report_key(wcombo, wacom->tool[1], prox); | 126 | input_report_key(input, wacom->tool[1], prox); |
121 | } | 127 | } |
122 | 128 | ||
123 | wacom->tool[0] = prox; /* Save proximity state */ | 129 | wacom->tool[0] = prox; /* Save proximity state */ |
124 | return 1; | 130 | return 1; |
125 | } | 131 | } |
126 | 132 | ||
127 | static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | 133 | static int wacom_ptu_irq(struct wacom_wac *wacom) |
128 | { | 134 | { |
129 | unsigned char *data = wacom->data; | 135 | unsigned char *data = wacom->data; |
136 | struct input_dev *input = wacom->input; | ||
130 | 137 | ||
131 | if (data[0] != WACOM_REPORT_PENABLED) { | 138 | if (data[0] != WACOM_REPORT_PENABLED) { |
132 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 139 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); |
@@ -134,40 +141,41 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | |||
134 | } | 141 | } |
135 | 142 | ||
136 | if (data[1] & 0x04) { | 143 | if (data[1] & 0x04) { |
137 | wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20); | 144 | input_report_key(input, BTN_TOOL_RUBBER, data[1] & 0x20); |
138 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08); | 145 | input_report_key(input, BTN_TOUCH, data[1] & 0x08); |
139 | wacom->id[0] = ERASER_DEVICE_ID; | 146 | wacom->id[0] = ERASER_DEVICE_ID; |
140 | } else { | 147 | } else { |
141 | wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20); | 148 | input_report_key(input, BTN_TOOL_PEN, data[1] & 0x20); |
142 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 149 | input_report_key(input, BTN_TOUCH, data[1] & 0x01); |
143 | wacom->id[0] = STYLUS_DEVICE_ID; | 150 | wacom->id[0] = STYLUS_DEVICE_ID; |
144 | } | 151 | } |
145 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | 152 | input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ |
146 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 153 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); |
147 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | 154 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); |
148 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | 155 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); |
149 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 156 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); |
150 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 157 | input_report_key(input, BTN_STYLUS2, data[1] & 0x10); |
151 | return 1; | 158 | return 1; |
152 | } | 159 | } |
153 | 160 | ||
154 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | 161 | static int wacom_graphire_irq(struct wacom_wac *wacom) |
155 | { | 162 | { |
156 | struct wacom_features *features = &wacom->features; | 163 | struct wacom_features *features = &wacom->features; |
157 | unsigned char *data = wacom->data; | 164 | unsigned char *data = wacom->data; |
158 | int x, y, rw; | 165 | struct input_dev *input = wacom->input; |
159 | static int penData = 0; | 166 | int prox; |
167 | int rw = 0; | ||
168 | int retval = 0; | ||
160 | 169 | ||
161 | if (data[0] != WACOM_REPORT_PENABLED) { | 170 | if (data[0] != WACOM_REPORT_PENABLED) { |
162 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | 171 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); |
163 | return 0; | 172 | goto exit; |
164 | } | 173 | } |
165 | 174 | ||
166 | if (data[1] & 0x80) { | 175 | prox = data[1] & 0x80; |
167 | /* in prox and not a pad data */ | 176 | if (prox || wacom->id[0]) { |
168 | penData = 1; | 177 | if (prox) { |
169 | 178 | switch ((data[1] >> 5) & 3) { | |
170 | switch ((data[1] >> 5) & 3) { | ||
171 | 179 | ||
172 | case 0: /* Pen */ | 180 | case 0: /* Pen */ |
173 | wacom->tool[0] = BTN_TOOL_PEN; | 181 | wacom->tool[0] = BTN_TOOL_PEN; |
@@ -180,128 +188,89 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
180 | break; | 188 | break; |
181 | 189 | ||
182 | case 2: /* Mouse with wheel */ | 190 | case 2: /* Mouse with wheel */ |
183 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | 191 | input_report_key(input, BTN_MIDDLE, data[1] & 0x04); |
184 | if (features->type == WACOM_G4 || features->type == WACOM_MO) { | ||
185 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
186 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | ||
187 | } else | ||
188 | wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | ||
189 | /* fall through */ | 192 | /* fall through */ |
190 | 193 | ||
191 | case 3: /* Mouse without wheel */ | 194 | case 3: /* Mouse without wheel */ |
192 | wacom->tool[0] = BTN_TOOL_MOUSE; | 195 | wacom->tool[0] = BTN_TOOL_MOUSE; |
193 | wacom->id[0] = CURSOR_DEVICE_ID; | 196 | wacom->id[0] = CURSOR_DEVICE_ID; |
194 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
195 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
196 | if (features->type == WACOM_G4 || features->type == WACOM_MO) | ||
197 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
198 | else | ||
199 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
200 | break; | 197 | break; |
198 | } | ||
201 | } | 199 | } |
202 | x = wacom_le16_to_cpu(&data[2]); | 200 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); |
203 | y = wacom_le16_to_cpu(&data[4]); | 201 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); |
204 | wacom_report_abs(wcombo, ABS_X, x); | ||
205 | wacom_report_abs(wcombo, ABS_Y, y); | ||
206 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { | 202 | if (wacom->tool[0] != BTN_TOOL_MOUSE) { |
207 | wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); | 203 | input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); |
208 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 204 | input_report_key(input, BTN_TOUCH, data[1] & 0x01); |
209 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 205 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); |
210 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | 206 | input_report_key(input, BTN_STYLUS2, data[1] & 0x04); |
211 | } | ||
212 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
213 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
214 | } else if (wacom->id[0]) { | ||
215 | wacom_report_abs(wcombo, ABS_X, 0); | ||
216 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
217 | if (wacom->tool[0] == BTN_TOOL_MOUSE) { | ||
218 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
219 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
220 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
221 | } else { | 207 | } else { |
222 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 208 | input_report_key(input, BTN_LEFT, data[1] & 0x01); |
223 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 209 | input_report_key(input, BTN_RIGHT, data[1] & 0x02); |
224 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 210 | if (features->type == WACOM_G4 || |
225 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 211 | features->type == WACOM_MO) { |
212 | input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f); | ||
213 | rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); | ||
214 | } else { | ||
215 | input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f); | ||
216 | rw = -(signed)data[6]; | ||
217 | } | ||
218 | input_report_rel(input, REL_WHEEL, rw); | ||
226 | } | 219 | } |
227 | wacom->id[0] = 0; | 220 | |
228 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 221 | if (!prox) |
229 | wacom_report_key(wcombo, wacom->tool[0], 0); | 222 | wacom->id[0] = 0; |
223 | input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
224 | input_report_key(input, wacom->tool[0], prox); | ||
225 | input_sync(input); /* sync last event */ | ||
230 | } | 226 | } |
231 | 227 | ||
232 | /* send pad data */ | 228 | /* send pad data */ |
233 | switch (features->type) { | 229 | switch (features->type) { |
234 | case WACOM_G4: | 230 | case WACOM_G4: |
235 | if (data[7] & 0xf8) { | 231 | prox = data[7] & 0xf8; |
236 | if (penData) { | 232 | if (prox || wacom->id[1]) { |
237 | wacom_input_sync(wcombo); /* sync last event */ | ||
238 | if (!wacom->id[0]) | ||
239 | penData = 0; | ||
240 | } | ||
241 | wacom->id[1] = PAD_DEVICE_ID; | 233 | wacom->id[1] = PAD_DEVICE_ID; |
242 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 234 | input_report_key(input, BTN_0, (data[7] & 0x40)); |
243 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 235 | input_report_key(input, BTN_4, (data[7] & 0x80)); |
244 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | 236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); |
245 | wacom_report_rel(wcombo, REL_WHEEL, rw); | 237 | input_report_rel(input, REL_WHEEL, rw); |
246 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 238 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); |
247 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 239 | if (!prox) |
248 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 240 | wacom->id[1] = 0; |
249 | } else if (wacom->id[1]) { | 241 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
250 | if (penData) { | 242 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); |
251 | wacom_input_sync(wcombo); /* sync last event */ | 243 | retval = 1; |
252 | if (!wacom->id[0]) | ||
253 | penData = 0; | ||
254 | } | ||
255 | wacom->id[1] = 0; | ||
256 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
257 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
258 | wacom_report_rel(wcombo, REL_WHEEL, 0); | ||
259 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
260 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
261 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
262 | } | 244 | } |
263 | break; | 245 | break; |
264 | case WACOM_MO: | 246 | |
265 | if ((data[7] & 0xf8) || (data[8] & 0xff)) { | 247 | case WACOM_MO: |
266 | if (penData) { | 248 | prox = (data[7] & 0xf8) || data[8]; |
267 | wacom_input_sync(wcombo); /* sync last event */ | 249 | if (prox || wacom->id[1]) { |
268 | if (!wacom->id[0]) | ||
269 | penData = 0; | ||
270 | } | ||
271 | wacom->id[1] = PAD_DEVICE_ID; | 250 | wacom->id[1] = PAD_DEVICE_ID; |
272 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 251 | input_report_key(input, BTN_0, (data[7] & 0x08)); |
273 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 252 | input_report_key(input, BTN_1, (data[7] & 0x20)); |
274 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | 253 | input_report_key(input, BTN_4, (data[7] & 0x10)); |
275 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | 254 | input_report_key(input, BTN_5, (data[7] & 0x40)); |
276 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | 255 | input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); |
277 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 256 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); |
278 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 257 | if (!prox) |
279 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 258 | wacom->id[1] = 0; |
280 | } else if (wacom->id[1]) { | 259 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
281 | if (penData) { | 260 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); |
282 | wacom_input_sync(wcombo); /* sync last event */ | ||
283 | if (!wacom->id[0]) | ||
284 | penData = 0; | ||
285 | } | ||
286 | wacom->id[1] = 0; | ||
287 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | ||
288 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | ||
289 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | ||
290 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | ||
291 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | ||
292 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
293 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
294 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
295 | } | 261 | } |
262 | retval = 1; | ||
296 | break; | 263 | break; |
297 | } | 264 | } |
298 | return 1; | 265 | exit: |
266 | return retval; | ||
299 | } | 267 | } |
300 | 268 | ||
301 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | 269 | static int wacom_intuos_inout(struct wacom_wac *wacom) |
302 | { | 270 | { |
303 | struct wacom_features *features = &wacom->features; | 271 | struct wacom_features *features = &wacom->features; |
304 | unsigned char *data = wacom->data; | 272 | unsigned char *data = wacom->data; |
273 | struct input_dev *input = wacom->input; | ||
305 | int idx = 0; | 274 | int idx = 0; |
306 | 275 | ||
307 | /* tool number */ | 276 | /* tool number */ |
@@ -316,64 +285,73 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
316 | (data[6] << 4) + (data[7] >> 4); | 285 | (data[6] << 4) + (data[7] >> 4); |
317 | 286 | ||
318 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); | 287 | wacom->id[idx] = (data[2] << 4) | (data[3] >> 4); |
288 | |||
319 | switch (wacom->id[idx]) { | 289 | switch (wacom->id[idx]) { |
320 | case 0x812: /* Inking pen */ | 290 | case 0x812: /* Inking pen */ |
321 | case 0x801: /* Intuos3 Inking pen */ | 291 | case 0x801: /* Intuos3 Inking pen */ |
322 | case 0x20802: /* Intuos4 Classic Pen */ | 292 | case 0x20802: /* Intuos4 Classic Pen */ |
323 | case 0x012: | 293 | case 0x012: |
324 | wacom->tool[idx] = BTN_TOOL_PENCIL; | 294 | wacom->tool[idx] = BTN_TOOL_PENCIL; |
325 | break; | 295 | break; |
326 | case 0x822: /* Pen */ | 296 | |
327 | case 0x842: | 297 | case 0x822: /* Pen */ |
328 | case 0x852: | 298 | case 0x842: |
329 | case 0x823: /* Intuos3 Grip Pen */ | 299 | case 0x852: |
330 | case 0x813: /* Intuos3 Classic Pen */ | 300 | case 0x823: /* Intuos3 Grip Pen */ |
331 | case 0x885: /* Intuos3 Marker Pen */ | 301 | case 0x813: /* Intuos3 Classic Pen */ |
332 | case 0x802: /* Intuos4 Grip Pen Eraser */ | 302 | case 0x885: /* Intuos3 Marker Pen */ |
333 | case 0x804: /* Intuos4 Marker Pen */ | 303 | case 0x802: /* Intuos4 Grip Pen Eraser */ |
334 | case 0x40802: /* Intuos4 Classic Pen */ | 304 | case 0x804: /* Intuos4 Marker Pen */ |
335 | case 0x022: | 305 | case 0x40802: /* Intuos4 Classic Pen */ |
336 | wacom->tool[idx] = BTN_TOOL_PEN; | 306 | case 0x022: |
337 | break; | 307 | wacom->tool[idx] = BTN_TOOL_PEN; |
338 | case 0x832: /* Stroke pen */ | 308 | break; |
339 | case 0x032: | 309 | |
340 | wacom->tool[idx] = BTN_TOOL_BRUSH; | 310 | case 0x832: /* Stroke pen */ |
341 | break; | 311 | case 0x032: |
342 | case 0x007: /* Mouse 4D and 2D */ | 312 | wacom->tool[idx] = BTN_TOOL_BRUSH; |
343 | case 0x09c: | 313 | break; |
344 | case 0x094: | 314 | |
345 | case 0x017: /* Intuos3 2D Mouse */ | 315 | case 0x007: /* Mouse 4D and 2D */ |
346 | case 0x806: /* Intuos4 Mouse */ | 316 | case 0x09c: |
347 | wacom->tool[idx] = BTN_TOOL_MOUSE; | 317 | case 0x094: |
348 | break; | 318 | case 0x017: /* Intuos3 2D Mouse */ |
349 | case 0x096: /* Lens cursor */ | 319 | case 0x806: /* Intuos4 Mouse */ |
350 | case 0x097: /* Intuos3 Lens cursor */ | 320 | wacom->tool[idx] = BTN_TOOL_MOUSE; |
351 | case 0x006: /* Intuos4 Lens cursor */ | 321 | break; |
352 | wacom->tool[idx] = BTN_TOOL_LENS; | 322 | |
353 | break; | 323 | case 0x096: /* Lens cursor */ |
354 | case 0x82a: /* Eraser */ | 324 | case 0x097: /* Intuos3 Lens cursor */ |
355 | case 0x85a: | 325 | case 0x006: /* Intuos4 Lens cursor */ |
356 | case 0x91a: | 326 | wacom->tool[idx] = BTN_TOOL_LENS; |
357 | case 0xd1a: | 327 | break; |
358 | case 0x0fa: | 328 | |
359 | case 0x82b: /* Intuos3 Grip Pen Eraser */ | 329 | case 0x82a: /* Eraser */ |
360 | case 0x81b: /* Intuos3 Classic Pen Eraser */ | 330 | case 0x85a: |
361 | case 0x91b: /* Intuos3 Airbrush Eraser */ | 331 | case 0x91a: |
362 | case 0x80c: /* Intuos4 Marker Pen Eraser */ | 332 | case 0xd1a: |
363 | case 0x80a: /* Intuos4 Grip Pen Eraser */ | 333 | case 0x0fa: |
364 | case 0x4080a: /* Intuos4 Classic Pen Eraser */ | 334 | case 0x82b: /* Intuos3 Grip Pen Eraser */ |
365 | case 0x90a: /* Intuos4 Airbrush Eraser */ | 335 | case 0x81b: /* Intuos3 Classic Pen Eraser */ |
366 | wacom->tool[idx] = BTN_TOOL_RUBBER; | 336 | case 0x91b: /* Intuos3 Airbrush Eraser */ |
367 | break; | 337 | case 0x80c: /* Intuos4 Marker Pen Eraser */ |
368 | case 0xd12: | 338 | case 0x80a: /* Intuos4 Grip Pen Eraser */ |
369 | case 0x912: | 339 | case 0x4080a: /* Intuos4 Classic Pen Eraser */ |
370 | case 0x112: | 340 | case 0x90a: /* Intuos4 Airbrush Eraser */ |
371 | case 0x913: /* Intuos3 Airbrush */ | 341 | wacom->tool[idx] = BTN_TOOL_RUBBER; |
372 | case 0x902: /* Intuos4 Airbrush */ | 342 | break; |
373 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | 343 | |
374 | break; | 344 | case 0xd12: |
375 | default: /* Unknown tool */ | 345 | case 0x912: |
376 | wacom->tool[idx] = BTN_TOOL_PEN; | 346 | case 0x112: |
347 | case 0x913: /* Intuos3 Airbrush */ | ||
348 | case 0x902: /* Intuos4 Airbrush */ | ||
349 | wacom->tool[idx] = BTN_TOOL_AIRBRUSH; | ||
350 | break; | ||
351 | |||
352 | default: /* Unknown tool */ | ||
353 | wacom->tool[idx] = BTN_TOOL_PEN; | ||
354 | break; | ||
377 | } | 355 | } |
378 | return 1; | 356 | return 1; |
379 | } | 357 | } |
@@ -384,41 +362,42 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
384 | * Reset all states otherwise we lose the initial states | 362 | * Reset all states otherwise we lose the initial states |
385 | * when in-prox next time | 363 | * when in-prox next time |
386 | */ | 364 | */ |
387 | wacom_report_abs(wcombo, ABS_X, 0); | 365 | input_report_abs(input, ABS_X, 0); |
388 | wacom_report_abs(wcombo, ABS_Y, 0); | 366 | input_report_abs(input, ABS_Y, 0); |
389 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | 367 | input_report_abs(input, ABS_DISTANCE, 0); |
390 | wacom_report_abs(wcombo, ABS_TILT_X, 0); | 368 | input_report_abs(input, ABS_TILT_X, 0); |
391 | wacom_report_abs(wcombo, ABS_TILT_Y, 0); | 369 | input_report_abs(input, ABS_TILT_Y, 0); |
392 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | 370 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { |
393 | wacom_report_key(wcombo, BTN_LEFT, 0); | 371 | input_report_key(input, BTN_LEFT, 0); |
394 | wacom_report_key(wcombo, BTN_MIDDLE, 0); | 372 | input_report_key(input, BTN_MIDDLE, 0); |
395 | wacom_report_key(wcombo, BTN_RIGHT, 0); | 373 | input_report_key(input, BTN_RIGHT, 0); |
396 | wacom_report_key(wcombo, BTN_SIDE, 0); | 374 | input_report_key(input, BTN_SIDE, 0); |
397 | wacom_report_key(wcombo, BTN_EXTRA, 0); | 375 | input_report_key(input, BTN_EXTRA, 0); |
398 | wacom_report_abs(wcombo, ABS_THROTTLE, 0); | 376 | input_report_abs(input, ABS_THROTTLE, 0); |
399 | wacom_report_abs(wcombo, ABS_RZ, 0); | 377 | input_report_abs(input, ABS_RZ, 0); |
400 | } else { | 378 | } else { |
401 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 379 | input_report_abs(input, ABS_PRESSURE, 0); |
402 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 380 | input_report_key(input, BTN_STYLUS, 0); |
403 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 381 | input_report_key(input, BTN_STYLUS2, 0); |
404 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 382 | input_report_key(input, BTN_TOUCH, 0); |
405 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 383 | input_report_abs(input, ABS_WHEEL, 0); |
406 | if (features->type >= INTUOS3S) | 384 | if (features->type >= INTUOS3S) |
407 | wacom_report_abs(wcombo, ABS_Z, 0); | 385 | input_report_abs(input, ABS_Z, 0); |
408 | } | 386 | } |
409 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 387 | input_report_key(input, wacom->tool[idx], 0); |
410 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 388 | input_report_abs(input, ABS_MISC, 0); /* reset tool id */ |
411 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 389 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
412 | wacom->id[idx] = 0; | 390 | wacom->id[idx] = 0; |
413 | return 2; | 391 | return 2; |
414 | } | 392 | } |
415 | return 0; | 393 | return 0; |
416 | } | 394 | } |
417 | 395 | ||
418 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | 396 | static void wacom_intuos_general(struct wacom_wac *wacom) |
419 | { | 397 | { |
420 | struct wacom_features *features = &wacom->features; | 398 | struct wacom_features *features = &wacom->features; |
421 | unsigned char *data = wacom->data; | 399 | unsigned char *data = wacom->data; |
400 | struct input_dev *input = wacom->input; | ||
422 | unsigned int t; | 401 | unsigned int t; |
423 | 402 | ||
424 | /* general pen packet */ | 403 | /* general pen packet */ |
@@ -426,30 +405,30 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | |||
426 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 405 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
427 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) | 406 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) |
428 | t = (t << 1) | (data[1] & 1); | 407 | t = (t << 1) | (data[1] & 1); |
429 | wacom_report_abs(wcombo, ABS_PRESSURE, t); | 408 | input_report_abs(input, ABS_PRESSURE, t); |
430 | wacom_report_abs(wcombo, ABS_TILT_X, | 409 | input_report_abs(input, ABS_TILT_X, |
431 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 410 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
432 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 411 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); |
433 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2); | 412 | input_report_key(input, BTN_STYLUS, data[1] & 2); |
434 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4); | 413 | input_report_key(input, BTN_STYLUS2, data[1] & 4); |
435 | wacom_report_key(wcombo, BTN_TOUCH, t > 10); | 414 | input_report_key(input, BTN_TOUCH, t > 10); |
436 | } | 415 | } |
437 | 416 | ||
438 | /* airbrush second packet */ | 417 | /* airbrush second packet */ |
439 | if ((data[1] & 0xbc) == 0xb4) { | 418 | if ((data[1] & 0xbc) == 0xb4) { |
440 | wacom_report_abs(wcombo, ABS_WHEEL, | 419 | input_report_abs(input, ABS_WHEEL, |
441 | (data[6] << 2) | ((data[7] >> 6) & 3)); | 420 | (data[6] << 2) | ((data[7] >> 6) & 3)); |
442 | wacom_report_abs(wcombo, ABS_TILT_X, | 421 | input_report_abs(input, ABS_TILT_X, |
443 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 422 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
444 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 423 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); |
445 | } | 424 | } |
446 | return; | ||
447 | } | 425 | } |
448 | 426 | ||
449 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | 427 | static int wacom_intuos_irq(struct wacom_wac *wacom) |
450 | { | 428 | { |
451 | struct wacom_features *features = &wacom->features; | 429 | struct wacom_features *features = &wacom->features; |
452 | unsigned char *data = wacom->data; | 430 | unsigned char *data = wacom->data; |
431 | struct input_dev *input = wacom->input; | ||
453 | unsigned int t; | 432 | unsigned int t; |
454 | int idx = 0, result; | 433 | int idx = 0, result; |
455 | 434 | ||
@@ -470,61 +449,61 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
470 | wacom->tool[1] = BTN_TOOL_FINGER; | 449 | wacom->tool[1] = BTN_TOOL_FINGER; |
471 | 450 | ||
472 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { | 451 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
473 | wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); | 452 | input_report_key(input, BTN_0, (data[2] & 0x01)); |
474 | wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); | 453 | input_report_key(input, BTN_1, (data[3] & 0x01)); |
475 | wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); | 454 | input_report_key(input, BTN_2, (data[3] & 0x02)); |
476 | wacom_report_key(wcombo, BTN_3, (data[3] & 0x04)); | 455 | input_report_key(input, BTN_3, (data[3] & 0x04)); |
477 | wacom_report_key(wcombo, BTN_4, (data[3] & 0x08)); | 456 | input_report_key(input, BTN_4, (data[3] & 0x08)); |
478 | wacom_report_key(wcombo, BTN_5, (data[3] & 0x10)); | 457 | input_report_key(input, BTN_5, (data[3] & 0x10)); |
479 | wacom_report_key(wcombo, BTN_6, (data[3] & 0x20)); | 458 | input_report_key(input, BTN_6, (data[3] & 0x20)); |
480 | if (data[1] & 0x80) { | 459 | if (data[1] & 0x80) { |
481 | wacom_report_abs(wcombo, ABS_WHEEL, (data[1] & 0x7f)); | 460 | input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f)); |
482 | } else { | 461 | } else { |
483 | /* Out of proximity, clear wheel value. */ | 462 | /* Out of proximity, clear wheel value. */ |
484 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 463 | input_report_abs(input, ABS_WHEEL, 0); |
485 | } | 464 | } |
486 | if (features->type != INTUOS4S) { | 465 | if (features->type != INTUOS4S) { |
487 | wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); | 466 | input_report_key(input, BTN_7, (data[3] & 0x40)); |
488 | wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); | 467 | input_report_key(input, BTN_8, (data[3] & 0x80)); |
489 | } | 468 | } |
490 | if (data[1] | (data[2] & 0x01) | data[3]) { | 469 | if (data[1] | (data[2] & 0x01) | data[3]) { |
491 | wacom_report_key(wcombo, wacom->tool[1], 1); | 470 | input_report_key(input, wacom->tool[1], 1); |
492 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | 471 | input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); |
493 | } else { | 472 | } else { |
494 | wacom_report_key(wcombo, wacom->tool[1], 0); | 473 | input_report_key(input, wacom->tool[1], 0); |
495 | wacom_report_abs(wcombo, ABS_MISC, 0); | 474 | input_report_abs(input, ABS_MISC, 0); |
496 | } | 475 | } |
497 | } else { | 476 | } else { |
498 | wacom_report_key(wcombo, BTN_0, (data[5] & 0x01)); | 477 | input_report_key(input, BTN_0, (data[5] & 0x01)); |
499 | wacom_report_key(wcombo, BTN_1, (data[5] & 0x02)); | 478 | input_report_key(input, BTN_1, (data[5] & 0x02)); |
500 | wacom_report_key(wcombo, BTN_2, (data[5] & 0x04)); | 479 | input_report_key(input, BTN_2, (data[5] & 0x04)); |
501 | wacom_report_key(wcombo, BTN_3, (data[5] & 0x08)); | 480 | input_report_key(input, BTN_3, (data[5] & 0x08)); |
502 | wacom_report_key(wcombo, BTN_4, (data[6] & 0x01)); | 481 | input_report_key(input, BTN_4, (data[6] & 0x01)); |
503 | wacom_report_key(wcombo, BTN_5, (data[6] & 0x02)); | 482 | input_report_key(input, BTN_5, (data[6] & 0x02)); |
504 | wacom_report_key(wcombo, BTN_6, (data[6] & 0x04)); | 483 | input_report_key(input, BTN_6, (data[6] & 0x04)); |
505 | wacom_report_key(wcombo, BTN_7, (data[6] & 0x08)); | 484 | input_report_key(input, BTN_7, (data[6] & 0x08)); |
506 | wacom_report_key(wcombo, BTN_8, (data[5] & 0x10)); | 485 | input_report_key(input, BTN_8, (data[5] & 0x10)); |
507 | wacom_report_key(wcombo, BTN_9, (data[6] & 0x10)); | 486 | input_report_key(input, BTN_9, (data[6] & 0x10)); |
508 | wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); | 487 | input_report_abs(input, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); |
509 | wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); | 488 | input_report_abs(input, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); |
510 | 489 | ||
511 | if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | | 490 | if ((data[5] & 0x1f) | (data[6] & 0x1f) | (data[1] & 0x1f) | |
512 | data[2] | (data[3] & 0x1f) | data[4]) { | 491 | data[2] | (data[3] & 0x1f) | data[4]) { |
513 | wacom_report_key(wcombo, wacom->tool[1], 1); | 492 | input_report_key(input, wacom->tool[1], 1); |
514 | wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID); | 493 | input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); |
515 | } else { | 494 | } else { |
516 | wacom_report_key(wcombo, wacom->tool[1], 0); | 495 | input_report_key(input, wacom->tool[1], 0); |
517 | wacom_report_abs(wcombo, ABS_MISC, 0); | 496 | input_report_abs(input, ABS_MISC, 0); |
518 | } | 497 | } |
519 | } | 498 | } |
520 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff); | 499 | input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff); |
521 | return 1; | 500 | return 1; |
522 | } | 501 | } |
523 | 502 | ||
524 | /* process in/out prox events */ | 503 | /* process in/out prox events */ |
525 | result = wacom_intuos_inout(wacom, wcombo); | 504 | result = wacom_intuos_inout(wacom); |
526 | if (result) | 505 | if (result) |
527 | return result-1; | 506 | return result - 1; |
528 | 507 | ||
529 | /* don't proceed if we don't know the ID */ | 508 | /* don't proceed if we don't know the ID */ |
530 | if (!wacom->id[idx]) | 509 | if (!wacom->id[idx]) |
@@ -545,17 +524,17 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
545 | return 0; | 524 | return 0; |
546 | 525 | ||
547 | if (features->type >= INTUOS3S) { | 526 | if (features->type >= INTUOS3S) { |
548 | wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | 527 | input_report_abs(input, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); |
549 | wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | 528 | input_report_abs(input, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); |
550 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | 529 | input_report_abs(input, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); |
551 | } else { | 530 | } else { |
552 | wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2])); | 531 | input_report_abs(input, ABS_X, be16_to_cpup((__be16 *)&data[2])); |
553 | wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4])); | 532 | input_report_abs(input, ABS_Y, be16_to_cpup((__be16 *)&data[4])); |
554 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); | 533 | input_report_abs(input, ABS_DISTANCE, ((data[9] >> 3) & 0x1f)); |
555 | } | 534 | } |
556 | 535 | ||
557 | /* process general packets */ | 536 | /* process general packets */ |
558 | wacom_intuos_general(wacom, wcombo); | 537 | wacom_intuos_general(wacom); |
559 | 538 | ||
560 | /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */ | 539 | /* 4D mouse, 2D mouse, marker pen rotation, tilt mouse, or Lens cursor packets */ |
561 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) { | 540 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0 || (data[1] & 0xbc) == 0xac) { |
@@ -567,174 +546,191 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
567 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | 546 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
568 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | 547 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : |
569 | ((t-1) / 2 + 450)) : (450 - t / 2) ; | 548 | ((t-1) / 2 + 450)) : (450 - t / 2) ; |
570 | wacom_report_abs(wcombo, ABS_Z, t); | 549 | input_report_abs(input, ABS_Z, t); |
571 | } else { | 550 | } else { |
572 | /* 4D mouse rotation packet */ | 551 | /* 4D mouse rotation packet */ |
573 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | 552 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
574 | wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ? | 553 | input_report_abs(input, ABS_RZ, (data[7] & 0x20) ? |
575 | ((t - 1) / 2) : -t / 2); | 554 | ((t - 1) / 2) : -t / 2); |
576 | } | 555 | } |
577 | 556 | ||
578 | } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { | 557 | } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { |
579 | /* 4D mouse packet */ | 558 | /* 4D mouse packet */ |
580 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | 559 | input_report_key(input, BTN_LEFT, data[8] & 0x01); |
581 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 560 | input_report_key(input, BTN_MIDDLE, data[8] & 0x02); |
582 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | 561 | input_report_key(input, BTN_RIGHT, data[8] & 0x04); |
583 | 562 | ||
584 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x20); | 563 | input_report_key(input, BTN_SIDE, data[8] & 0x20); |
585 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x10); | 564 | input_report_key(input, BTN_EXTRA, data[8] & 0x10); |
586 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 565 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
587 | wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | 566 | input_report_abs(input, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); |
588 | 567 | ||
589 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | 568 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
590 | /* I4 mouse */ | 569 | /* I4 mouse */ |
591 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { | 570 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
592 | wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); | 571 | input_report_key(input, BTN_LEFT, data[6] & 0x01); |
593 | wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); | 572 | input_report_key(input, BTN_MIDDLE, data[6] & 0x02); |
594 | wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); | 573 | input_report_key(input, BTN_RIGHT, data[6] & 0x04); |
595 | wacom_report_rel(wcombo, REL_WHEEL, ((data[7] & 0x80) >> 7) | 574 | input_report_rel(input, REL_WHEEL, ((data[7] & 0x80) >> 7) |
596 | - ((data[7] & 0x40) >> 6)); | 575 | - ((data[7] & 0x40) >> 6)); |
597 | wacom_report_key(wcombo, BTN_SIDE, data[6] & 0x08); | 576 | input_report_key(input, BTN_SIDE, data[6] & 0x08); |
598 | wacom_report_key(wcombo, BTN_EXTRA, data[6] & 0x10); | 577 | input_report_key(input, BTN_EXTRA, data[6] & 0x10); |
599 | 578 | ||
600 | wacom_report_abs(wcombo, ABS_TILT_X, | 579 | input_report_abs(input, ABS_TILT_X, |
601 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 580 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); |
602 | wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f); | 581 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); |
603 | } else { | 582 | } else { |
604 | /* 2D mouse packet */ | 583 | /* 2D mouse packet */ |
605 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x04); | 584 | input_report_key(input, BTN_LEFT, data[8] & 0x04); |
606 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08); | 585 | input_report_key(input, BTN_MIDDLE, data[8] & 0x08); |
607 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x10); | 586 | input_report_key(input, BTN_RIGHT, data[8] & 0x10); |
608 | wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01) | 587 | input_report_rel(input, REL_WHEEL, (data[8] & 0x01) |
609 | - ((data[8] & 0x02) >> 1)); | 588 | - ((data[8] & 0x02) >> 1)); |
610 | 589 | ||
611 | /* I3 2D mouse side buttons */ | 590 | /* I3 2D mouse side buttons */ |
612 | if (features->type >= INTUOS3S && features->type <= INTUOS3L) { | 591 | if (features->type >= INTUOS3S && features->type <= INTUOS3L) { |
613 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); | 592 | input_report_key(input, BTN_SIDE, data[8] & 0x40); |
614 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); | 593 | input_report_key(input, BTN_EXTRA, data[8] & 0x20); |
615 | } | 594 | } |
616 | } | 595 | } |
617 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || | 596 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || |
618 | features->type == INTUOS4L) && | 597 | features->type == INTUOS4L) && |
619 | wacom->tool[idx] == BTN_TOOL_LENS) { | 598 | wacom->tool[idx] == BTN_TOOL_LENS) { |
620 | /* Lens cursor packets */ | 599 | /* Lens cursor packets */ |
621 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | 600 | input_report_key(input, BTN_LEFT, data[8] & 0x01); |
622 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 601 | input_report_key(input, BTN_MIDDLE, data[8] & 0x02); |
623 | wacom_report_key(wcombo, BTN_RIGHT, data[8] & 0x04); | 602 | input_report_key(input, BTN_RIGHT, data[8] & 0x04); |
624 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x10); | 603 | input_report_key(input, BTN_SIDE, data[8] & 0x10); |
625 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x08); | 604 | input_report_key(input, BTN_EXTRA, data[8] & 0x08); |
626 | } | 605 | } |
627 | } | 606 | } |
628 | 607 | ||
629 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ | 608 | input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */ |
630 | wacom_report_key(wcombo, wacom->tool[idx], 1); | 609 | input_report_key(input, wacom->tool[idx], 1); |
631 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 610 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
632 | return 1; | 611 | return 1; |
633 | } | 612 | } |
634 | 613 | ||
635 | 614 | ||
636 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) | 615 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) |
637 | { | 616 | { |
638 | wacom_report_abs(wcombo, ABS_X, | 617 | struct input_dev *input = wacom->input; |
639 | (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); | 618 | int finger = idx + 1; |
640 | wacom_report_abs(wcombo, ABS_Y, | 619 | int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; |
641 | (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); | 620 | int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; |
642 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 621 | |
643 | wacom_report_key(wcombo, wacom->tool[idx], 1); | 622 | /* |
644 | if (idx) | 623 | * Work around input core suppressing "duplicate" events since |
645 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 624 | * we are abusing ABS_X/ABS_Y to transmit multi-finger data. |
646 | else | 625 | * This should go away once we switch to true multitouch |
647 | wacom_report_key(wcombo, BTN_TOUCH, 1); | 626 | * protocol. |
627 | */ | ||
628 | if (wacom->last_finger != finger) { | ||
629 | if (x == input->abs[ABS_X]) | ||
630 | x++; | ||
631 | |||
632 | if (y == input->abs[ABS_Y]) | ||
633 | y++; | ||
634 | } | ||
635 | |||
636 | input_report_abs(input, ABS_X, x); | ||
637 | input_report_abs(input, ABS_Y, y); | ||
638 | input_report_abs(input, ABS_MISC, wacom->id[0]); | ||
639 | input_report_key(input, wacom->tool[finger], 1); | ||
640 | if (!idx) | ||
641 | input_report_key(input, BTN_TOUCH, 1); | ||
642 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
643 | input_sync(wacom->input); | ||
644 | |||
645 | wacom->last_finger = finger; | ||
648 | } | 646 | } |
649 | 647 | ||
650 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) | 648 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) |
651 | { | 649 | { |
652 | wacom_report_abs(wcombo, ABS_X, 0); | 650 | struct input_dev *input = wacom->input; |
653 | wacom_report_abs(wcombo, ABS_Y, 0); | 651 | int finger = idx + 1; |
654 | wacom_report_abs(wcombo, ABS_MISC, 0); | 652 | |
655 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 653 | input_report_abs(input, ABS_X, 0); |
656 | if (idx) | 654 | input_report_abs(input, ABS_Y, 0); |
657 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 655 | input_report_abs(input, ABS_MISC, 0); |
658 | else | 656 | input_report_key(input, wacom->tool[finger], 0); |
659 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 657 | if (!idx) |
660 | return; | 658 | input_report_key(input, BTN_TOUCH, 0); |
659 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
660 | input_sync(input); | ||
661 | } | 661 | } |
662 | 662 | ||
663 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) | 663 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) |
664 | { | 664 | { |
665 | char *data = wacom->data; | 665 | char *data = wacom->data; |
666 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 666 | struct input_dev *input = wacom->input; |
667 | static int firstFinger = 0; | ||
668 | static int secondFinger = 0; | ||
669 | 667 | ||
670 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | 668 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; |
671 | wacom->id[0] = TOUCH_DEVICE_ID; | 669 | wacom->id[0] = TOUCH_DEVICE_ID; |
672 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | 670 | wacom->tool[2] = BTN_TOOL_TRIPLETAP; |
671 | |||
672 | if (len != WACOM_PKGLEN_TPC1FG) { | ||
673 | 673 | ||
674 | if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { | ||
675 | switch (data[0]) { | 674 | switch (data[0]) { |
676 | case WACOM_REPORT_TPC1FG: | ||
677 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
678 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
679 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
680 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
681 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
682 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
683 | break; | ||
684 | case WACOM_REPORT_TPC2FG: | ||
685 | /* keep this byte to send proper out-prox event */ | ||
686 | wacom->id[1] = data[1] & 0x03; | ||
687 | |||
688 | if (data[1] & 0x01) { | ||
689 | wacom_tpc_finger_in(wacom, wcombo, data, 0); | ||
690 | firstFinger = 1; | ||
691 | } else if (firstFinger) { | ||
692 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
693 | } | ||
694 | 675 | ||
695 | if (data[1] & 0x02) { | 676 | case WACOM_REPORT_TPC1FG: |
696 | /* sync first finger data */ | 677 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); |
697 | if (firstFinger) | 678 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); |
698 | wacom_input_sync(wcombo); | 679 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); |
680 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); | ||
681 | input_report_abs(input, ABS_MISC, wacom->id[0]); | ||
682 | input_report_key(input, wacom->tool[1], 1); | ||
683 | input_sync(input); | ||
684 | break; | ||
699 | 685 | ||
700 | wacom_tpc_finger_in(wacom, wcombo, data, 1); | 686 | case WACOM_REPORT_TPC2FG: |
701 | secondFinger = 1; | 687 | if (data[1] & 0x01) |
702 | } else if (secondFinger) { | 688 | wacom_tpc_finger_in(wacom, data, 0); |
703 | /* sync first finger data */ | 689 | else if (wacom->id[1] & 0x01) |
704 | if (firstFinger) | 690 | wacom_tpc_touch_out(wacom, 0); |
705 | wacom_input_sync(wcombo); | ||
706 | 691 | ||
707 | wacom_tpc_touch_out(wacom, wcombo, 1); | 692 | if (data[1] & 0x02) |
708 | secondFinger = 0; | 693 | wacom_tpc_finger_in(wacom, data, 1); |
709 | } | 694 | else if (wacom->id[1] & 0x02) |
710 | if (!(data[1] & 0x01)) | 695 | wacom_tpc_touch_out(wacom, 1); |
711 | firstFinger = 0; | 696 | break; |
712 | break; | ||
713 | } | 697 | } |
714 | } else { | 698 | } else { |
715 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | 699 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); |
716 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | 700 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); |
717 | wacom_report_key(wcombo, BTN_TOUCH, 1); | 701 | input_report_key(input, BTN_TOUCH, 1); |
718 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 702 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
719 | wacom_report_key(wcombo, wacom->tool[0], 1); | 703 | input_report_key(input, wacom->tool[1], 1); |
704 | input_sync(input); | ||
720 | } | 705 | } |
721 | return; | ||
722 | } | 706 | } |
723 | 707 | ||
724 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | 708 | static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) |
725 | { | 709 | { |
726 | struct wacom_features *features = &wacom->features; | 710 | struct wacom_features *features = &wacom->features; |
727 | char *data = wacom->data; | 711 | char *data = wacom->data; |
728 | int prox = 0, pressure, idx = -1; | 712 | struct input_dev *input = wacom->input; |
729 | static int stylusInProx, touchInProx = 1, touchOut; | 713 | int prox = 0, pressure; |
730 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 714 | int retval = 0; |
731 | 715 | ||
732 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 716 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
733 | 717 | ||
734 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG || /* single touch */ | 718 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ |
735 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ | 719 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ |
736 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ | 720 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ |
737 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ | 721 | |
722 | if (wacom->shared->stylus_in_proximity) { | ||
723 | if (wacom->id[1] & 0x01) | ||
724 | wacom_tpc_touch_out(wacom, 0); | ||
725 | |||
726 | if (wacom->id[1] & 0x02) | ||
727 | wacom_tpc_touch_out(wacom, 1); | ||
728 | |||
729 | wacom->id[1] = 0; | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ | ||
738 | prox = data[0] & 0x01; | 734 | prox = data[0] & 0x01; |
739 | } else { /* with capacity */ | 735 | } else { /* with capacity */ |
740 | if (data[0] == WACOM_REPORT_TPC1FG) | 736 | if (data[0] == WACOM_REPORT_TPC1FG) |
@@ -745,168 +741,264 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
745 | prox = data[1] & 0x03; | 741 | prox = data[1] & 0x03; |
746 | } | 742 | } |
747 | 743 | ||
748 | if (!stylusInProx) { /* stylus not in prox */ | 744 | if (prox) { |
749 | if (prox) { | 745 | if (!wacom->id[1]) |
750 | if (touchInProx) { | 746 | wacom->last_finger = 1; |
751 | wacom_tpc_touch_in(wacom, wcombo); | 747 | wacom_tpc_touch_in(wacom, len); |
752 | touchOut = 1; | 748 | } else { |
753 | return 1; | 749 | if (data[0] == WACOM_REPORT_TPC2FG) { |
754 | } | ||
755 | } else { | ||
756 | /* 2FGT out-prox */ | 750 | /* 2FGT out-prox */ |
757 | if (data[0] == WACOM_REPORT_TPC2FG) { | 751 | if (wacom->id[1] & 0x01) |
758 | idx = (wacom->id[1] & 0x01) - 1; | 752 | wacom_tpc_touch_out(wacom, 0); |
759 | if (idx == 0) { | 753 | |
760 | wacom_tpc_touch_out(wacom, wcombo, idx); | 754 | if (wacom->id[1] & 0x02) |
761 | /* sync first finger event */ | 755 | wacom_tpc_touch_out(wacom, 1); |
762 | if (wacom->id[1] & 0x02) | 756 | } else |
763 | wacom_input_sync(wcombo); | 757 | /* one finger touch */ |
764 | } | 758 | wacom_tpc_touch_out(wacom, 0); |
765 | idx = (wacom->id[1] & 0x02) - 1; | 759 | |
766 | if (idx == 1) | 760 | wacom->id[0] = 0; |
767 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
768 | } else /* one finger touch */ | ||
769 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
770 | touchOut = 0; | ||
771 | touchInProx = 1; | ||
772 | return 1; | ||
773 | } | ||
774 | } else if (touchOut || !prox) { /* force touch out-prox */ | ||
775 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
776 | touchOut = 0; | ||
777 | touchInProx = 1; | ||
778 | return 1; | ||
779 | } | 761 | } |
762 | /* keep prox bit to send proper out-prox event */ | ||
763 | wacom->id[1] = prox; | ||
780 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ | 764 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ |
781 | prox = data[1] & 0x20; | 765 | prox = data[1] & 0x20; |
782 | 766 | ||
783 | touchInProx = 0; | 767 | if (!wacom->shared->stylus_in_proximity) { /* first in prox */ |
768 | /* Going into proximity select tool */ | ||
769 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
770 | if (wacom->tool[0] == BTN_TOOL_PEN) | ||
771 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
772 | else | ||
773 | wacom->id[0] = ERASER_DEVICE_ID; | ||
784 | 774 | ||
785 | if (prox) { /* in prox */ | 775 | wacom->shared->stylus_in_proximity = true; |
786 | if (!wacom->id[0]) { | 776 | } |
787 | /* Going into proximity select tool */ | 777 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); |
788 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 778 | input_report_key(input, BTN_STYLUS2, data[1] & 0x10); |
789 | if (wacom->tool[0] == BTN_TOOL_PEN) | 779 | input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); |
790 | wacom->id[0] = STYLUS_DEVICE_ID; | 780 | input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); |
791 | else | 781 | pressure = ((data[7] & 0x01) << 8) | data[6]; |
792 | wacom->id[0] = ERASER_DEVICE_ID; | 782 | if (pressure < 0) |
793 | } | 783 | pressure = features->pressure_max + pressure + 1; |
794 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 784 | input_report_abs(input, ABS_PRESSURE, pressure); |
795 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 785 | input_report_key(input, BTN_TOUCH, data[1] & 0x05); |
796 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | 786 | if (!prox) { /* out-prox */ |
797 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
798 | pressure = ((data[7] & 0x01) << 8) | data[6]; | ||
799 | if (pressure < 0) | ||
800 | pressure = features->pressure_max + pressure + 1; | ||
801 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | ||
802 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); | ||
803 | } else { | ||
804 | wacom_report_abs(wcombo, ABS_X, 0); | ||
805 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
806 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
807 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
808 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
809 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
810 | wacom->id[0] = 0; | 787 | wacom->id[0] = 0; |
811 | /* pen is out so touch can be enabled now */ | 788 | wacom->shared->stylus_in_proximity = false; |
812 | touchInProx = 1; | ||
813 | } | 789 | } |
814 | wacom_report_key(wcombo, wacom->tool[0], prox); | 790 | input_report_key(input, wacom->tool[0], prox); |
815 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 791 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
816 | stylusInProx = prox; | 792 | retval = 1; |
817 | return 1; | ||
818 | } | 793 | } |
819 | return 0; | 794 | return retval; |
820 | } | 795 | } |
821 | 796 | ||
822 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | 797 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
823 | { | 798 | { |
799 | bool sync; | ||
800 | |||
824 | switch (wacom_wac->features.type) { | 801 | switch (wacom_wac->features.type) { |
825 | case PENPARTNER: | 802 | case PENPARTNER: |
826 | return wacom_penpartner_irq(wacom_wac, wcombo); | 803 | sync = wacom_penpartner_irq(wacom_wac); |
827 | 804 | break; | |
828 | case PL: | 805 | |
829 | return wacom_pl_irq(wacom_wac, wcombo); | 806 | case PL: |
830 | 807 | sync = wacom_pl_irq(wacom_wac); | |
831 | case WACOM_G4: | 808 | break; |
832 | case GRAPHIRE: | 809 | |
833 | case WACOM_MO: | 810 | case WACOM_G4: |
834 | return wacom_graphire_irq(wacom_wac, wcombo); | 811 | case GRAPHIRE: |
835 | 812 | case WACOM_MO: | |
836 | case PTU: | 813 | sync = wacom_graphire_irq(wacom_wac); |
837 | return wacom_ptu_irq(wacom_wac, wcombo); | 814 | break; |
838 | 815 | ||
839 | case INTUOS: | 816 | case PTU: |
840 | case INTUOS3S: | 817 | sync = wacom_ptu_irq(wacom_wac); |
841 | case INTUOS3: | 818 | break; |
842 | case INTUOS3L: | 819 | |
843 | case INTUOS4S: | 820 | case INTUOS: |
844 | case INTUOS4: | 821 | case INTUOS3S: |
845 | case INTUOS4L: | 822 | case INTUOS3: |
846 | case CINTIQ: | 823 | case INTUOS3L: |
847 | case WACOM_BEE: | 824 | case INTUOS4S: |
848 | return wacom_intuos_irq(wacom_wac, wcombo); | 825 | case INTUOS4: |
849 | 826 | case INTUOS4L: | |
850 | case TABLETPC: | 827 | case CINTIQ: |
851 | case TABLETPC2FG: | 828 | case WACOM_BEE: |
852 | return wacom_tpc_irq(wacom_wac, wcombo); | 829 | sync = wacom_intuos_irq(wacom_wac); |
853 | 830 | break; | |
854 | default: | 831 | |
855 | return 0; | 832 | case TABLETPC: |
833 | case TABLETPC2FG: | ||
834 | sync = wacom_tpc_irq(wacom_wac, len); | ||
835 | break; | ||
836 | |||
837 | default: | ||
838 | sync = false; | ||
839 | break; | ||
856 | } | 840 | } |
857 | return 0; | 841 | |
842 | if (sync) | ||
843 | input_sync(wacom_wac->input); | ||
844 | } | ||
845 | |||
846 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | ||
847 | { | ||
848 | struct input_dev *input_dev = wacom_wac->input; | ||
849 | |||
850 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); | ||
851 | input_set_capability(input_dev, EV_REL, REL_WHEEL); | ||
852 | |||
853 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
854 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
855 | __set_bit(BTN_MIDDLE, input_dev->keybit); | ||
856 | __set_bit(BTN_SIDE, input_dev->keybit); | ||
857 | __set_bit(BTN_EXTRA, input_dev->keybit); | ||
858 | |||
859 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
860 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | ||
861 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); | ||
862 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); | ||
863 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); | ||
864 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); | ||
865 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); | ||
866 | __set_bit(BTN_STYLUS, input_dev->keybit); | ||
867 | __set_bit(BTN_STYLUS2, input_dev->keybit); | ||
868 | |||
869 | input_set_abs_params(input_dev, ABS_DISTANCE, | ||
870 | 0, wacom_wac->features.distance_max, 0, 0); | ||
871 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | ||
872 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | ||
873 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | ||
874 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | ||
875 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | ||
858 | } | 876 | } |
859 | 877 | ||
860 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 878 | void wacom_setup_input_capabilities(struct input_dev *input_dev, |
879 | struct wacom_wac *wacom_wac) | ||
861 | { | 880 | { |
881 | struct wacom_features *features = &wacom_wac->features; | ||
882 | int i; | ||
883 | |||
884 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
885 | |||
886 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
887 | |||
888 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); | ||
889 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); | ||
890 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); | ||
891 | |||
892 | __set_bit(ABS_MISC, input_dev->absbit); | ||
893 | |||
862 | switch (wacom_wac->features.type) { | 894 | switch (wacom_wac->features.type) { |
863 | case WACOM_MO: | 895 | case WACOM_MO: |
864 | input_dev_mo(input_dev, wacom_wac); | 896 | __set_bit(BTN_1, input_dev->keybit); |
865 | case WACOM_G4: | 897 | __set_bit(BTN_5, input_dev->keybit); |
866 | input_dev_g4(input_dev, wacom_wac); | 898 | |
867 | /* fall through */ | 899 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); |
868 | case GRAPHIRE: | 900 | /* fall through */ |
869 | input_dev_g(input_dev, wacom_wac); | 901 | |
870 | break; | 902 | case WACOM_G4: |
871 | case WACOM_BEE: | 903 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); |
872 | input_dev_bee(input_dev, wacom_wac); | 904 | |
873 | case INTUOS3: | 905 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
874 | case INTUOS3L: | 906 | __set_bit(BTN_0, input_dev->keybit); |
875 | case CINTIQ: | 907 | __set_bit(BTN_4, input_dev->keybit); |
876 | input_dev_i3(input_dev, wacom_wac); | 908 | /* fall through */ |
877 | /* fall through */ | 909 | |
878 | case INTUOS3S: | 910 | case GRAPHIRE: |
879 | input_dev_i3s(input_dev, wacom_wac); | 911 | input_set_capability(input_dev, EV_REL, REL_WHEEL); |
880 | /* fall through */ | 912 | |
881 | case INTUOS: | 913 | __set_bit(BTN_LEFT, input_dev->keybit); |
882 | input_dev_i(input_dev, wacom_wac); | 914 | __set_bit(BTN_RIGHT, input_dev->keybit); |
883 | break; | 915 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
884 | case INTUOS4: | 916 | |
885 | case INTUOS4L: | 917 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); |
886 | input_dev_i4(input_dev, wacom_wac); | 918 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
887 | /* fall through */ | 919 | __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); |
888 | case INTUOS4S: | 920 | __set_bit(BTN_STYLUS, input_dev->keybit); |
889 | input_dev_i4s(input_dev, wacom_wac); | 921 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
890 | input_dev_i(input_dev, wacom_wac); | 922 | break; |
891 | break; | 923 | |
892 | case TABLETPC2FG: | 924 | case WACOM_BEE: |
893 | input_dev_tpc2fg(input_dev, wacom_wac); | 925 | __set_bit(BTN_8, input_dev->keybit); |
894 | /* fall through */ | 926 | __set_bit(BTN_9, input_dev->keybit); |
895 | case TABLETPC: | 927 | /* fall through */ |
896 | input_dev_tpc(input_dev, wacom_wac); | 928 | |
897 | if (wacom_wac->features.device_type != BTN_TOOL_PEN) | 929 | case INTUOS3: |
898 | break; /* no need to process stylus stuff */ | 930 | case INTUOS3L: |
899 | 931 | case CINTIQ: | |
900 | /* fall through */ | 932 | __set_bit(BTN_4, input_dev->keybit); |
901 | case PL: | 933 | __set_bit(BTN_5, input_dev->keybit); |
902 | case PTU: | 934 | __set_bit(BTN_6, input_dev->keybit); |
903 | input_dev_pl(input_dev, wacom_wac); | 935 | __set_bit(BTN_7, input_dev->keybit); |
904 | /* fall through */ | 936 | |
905 | case PENPARTNER: | 937 | input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); |
906 | input_dev_pt(input_dev, wacom_wac); | 938 | /* fall through */ |
907 | break; | 939 | |
940 | case INTUOS3S: | ||
941 | __set_bit(BTN_0, input_dev->keybit); | ||
942 | __set_bit(BTN_1, input_dev->keybit); | ||
943 | __set_bit(BTN_2, input_dev->keybit); | ||
944 | __set_bit(BTN_3, input_dev->keybit); | ||
945 | |||
946 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
947 | |||
948 | input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); | ||
949 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
950 | /* fall through */ | ||
951 | |||
952 | case INTUOS: | ||
953 | wacom_setup_intuos(wacom_wac); | ||
954 | break; | ||
955 | |||
956 | case INTUOS4: | ||
957 | case INTUOS4L: | ||
958 | __set_bit(BTN_7, input_dev->keybit); | ||
959 | __set_bit(BTN_8, input_dev->keybit); | ||
960 | /* fall through */ | ||
961 | |||
962 | case INTUOS4S: | ||
963 | for (i = 0; i < 7; i++) | ||
964 | __set_bit(BTN_0 + i, input_dev->keybit); | ||
965 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
966 | |||
967 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
968 | wacom_setup_intuos(wacom_wac); | ||
969 | break; | ||
970 | |||
971 | case TABLETPC2FG: | ||
972 | if (features->device_type == BTN_TOOL_TRIPLETAP) { | ||
973 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
974 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); | ||
975 | } | ||
976 | /* fall through */ | ||
977 | |||
978 | case TABLETPC: | ||
979 | if (features->device_type == BTN_TOOL_DOUBLETAP || | ||
980 | features->device_type == BTN_TOOL_TRIPLETAP) { | ||
981 | input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); | ||
982 | input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); | ||
983 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
984 | } | ||
985 | |||
986 | if (features->device_type != BTN_TOOL_PEN) | ||
987 | break; /* no need to process stylus stuff */ | ||
988 | |||
989 | /* fall through */ | ||
990 | |||
991 | case PL: | ||
992 | case PTU: | ||
993 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | ||
994 | __set_bit(BTN_STYLUS, input_dev->keybit); | ||
995 | __set_bit(BTN_STYLUS2, input_dev->keybit); | ||
996 | /* fall through */ | ||
997 | |||
998 | case PENPARTNER: | ||
999 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
1000 | break; | ||
908 | } | 1001 | } |
909 | return; | ||
910 | } | 1002 | } |
911 | 1003 | ||
912 | static const struct wacom_features wacom_features_0x00 = | 1004 | static const struct wacom_features wacom_features_0x00 = |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index b50cf04e61a..063f1af3204 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #ifndef WACOM_WAC_H | 9 | #ifndef WACOM_WAC_H |
10 | #define WACOM_WAC_H | 10 | #define WACOM_WAC_H |
11 | 11 | ||
12 | #include <linux/types.h> | ||
13 | |||
12 | /* maximum packet length for USB devices */ | 14 | /* maximum packet length for USB devices */ |
13 | #define WACOM_PKGLEN_MAX 32 | 15 | #define WACOM_PKGLEN_MAX 32 |
14 | 16 | ||
@@ -71,13 +73,20 @@ struct wacom_features { | |||
71 | unsigned char unitExpo; | 73 | unsigned char unitExpo; |
72 | }; | 74 | }; |
73 | 75 | ||
76 | struct wacom_shared { | ||
77 | bool stylus_in_proximity; | ||
78 | }; | ||
79 | |||
74 | struct wacom_wac { | 80 | struct wacom_wac { |
75 | char name[64]; | 81 | char name[64]; |
76 | unsigned char *data; | 82 | unsigned char *data; |
77 | int tool[2]; | 83 | int tool[3]; |
78 | int id[2]; | 84 | int id[3]; |
79 | __u32 serial[2]; | 85 | __u32 serial[2]; |
86 | int last_finger; | ||
80 | struct wacom_features features; | 87 | struct wacom_features features; |
88 | struct wacom_shared *shared; | ||
89 | struct input_dev *input; | ||
81 | }; | 90 | }; |
82 | 91 | ||
83 | #endif | 92 | #endif |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a..b9f58ca82fd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY | |||
99 | To compile this driver as a module, choose M here: the | 99 | To compile this driver as a module, choose M here: the |
100 | module will be called h3600_ts_input. | 100 | module will be called h3600_ts_input. |
101 | 101 | ||
102 | config TOUCHSCREEN_CORGI | ||
103 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" | ||
104 | depends on PXA_SHARPSL | ||
105 | select CORGI_SSP_DEPRECATED | ||
106 | help | ||
107 | Say Y here to enable the driver for the touchscreen on the | ||
108 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. | ||
109 | |||
110 | If unsure, say N. | ||
111 | |||
112 | To compile this driver as a module, choose M here: the | ||
113 | module will be called corgi_ts. | ||
114 | |||
115 | NOTE: this driver is deprecated, try enable SPI and generic | ||
116 | ADS7846-based touchscreen driver. | ||
117 | |||
118 | config TOUCHSCREEN_DA9034 | 102 | config TOUCHSCREEN_DA9034 |
119 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 103 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
120 | depends on PMIC_DA903X | 104 | depends on PMIC_DA903X |
@@ -135,6 +119,18 @@ config TOUCHSCREEN_DYNAPRO | |||
135 | To compile this driver as a module, choose M here: the | 119 | To compile this driver as a module, choose M here: the |
136 | module will be called dynapro. | 120 | module will be called dynapro. |
137 | 121 | ||
122 | config TOUCHSCREEN_HAMPSHIRE | ||
123 | tristate "Hampshire serial touchscreen" | ||
124 | select SERIO | ||
125 | help | ||
126 | Say Y here if you have a Hampshire serial touchscreen connected to | ||
127 | your system. | ||
128 | |||
129 | If unsure, say N. | ||
130 | |||
131 | To compile this driver as a module, choose M here: the | ||
132 | module will be called hampshire. | ||
133 | |||
138 | config TOUCHSCREEN_EETI | 134 | config TOUCHSCREEN_EETI |
139 | tristate "EETI touchscreen panel support" | 135 | tristate "EETI touchscreen panel support" |
140 | depends on I2C | 136 | depends on I2C |
@@ -158,8 +154,8 @@ config TOUCHSCREEN_FUJITSU | |||
158 | module will be called fujitsu-ts. | 154 | module will be called fujitsu-ts. |
159 | 155 | ||
160 | config TOUCHSCREEN_S3C2410 | 156 | config TOUCHSCREEN_S3C2410 |
161 | tristate "Samsung S3C2410 touchscreen input driver" | 157 | tristate "Samsung S3C2410/generic touchscreen input driver" |
162 | depends on ARCH_S3C2410 | 158 | depends on ARCH_S3C2410 || SAMSUNG_DEV_TS |
163 | select S3C24XX_ADC | 159 | select S3C24XX_ADC |
164 | help | 160 | help |
165 | Say Y here if you have the s3c2410 touchscreen. | 161 | Say Y here if you have the s3c2410 touchscreen. |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca2..8ad36eef90a 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -12,8 +12,8 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | |||
12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
15 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | ||
16 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 15 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
16 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | ||
17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
19 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 19 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e019d53d1ab..0d2d7e54b46 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -156,9 +156,14 @@ struct ser_req { | |||
156 | u16 reset; | 156 | u16 reset; |
157 | u16 ref_on; | 157 | u16 ref_on; |
158 | u16 command; | 158 | u16 command; |
159 | u16 sample; | ||
160 | struct spi_message msg; | 159 | struct spi_message msg; |
161 | struct spi_transfer xfer[6]; | 160 | struct spi_transfer xfer[6]; |
161 | |||
162 | /* | ||
163 | * DMA (thus cache coherency maintenance) requires the | ||
164 | * transfer buffers to live in their own cache lines. | ||
165 | */ | ||
166 | u16 sample ____cacheline_aligned; | ||
162 | }; | 167 | }; |
163 | 168 | ||
164 | struct ad7877 { | 169 | struct ad7877 { |
@@ -182,8 +187,6 @@ struct ad7877 { | |||
182 | u8 averaging; | 187 | u8 averaging; |
183 | u8 pen_down_acc_interval; | 188 | u8 pen_down_acc_interval; |
184 | 189 | ||
185 | u16 conversion_data[AD7877_NR_SENSE]; | ||
186 | |||
187 | struct spi_transfer xfer[AD7877_NR_SENSE + 2]; | 190 | struct spi_transfer xfer[AD7877_NR_SENSE + 2]; |
188 | struct spi_message msg; | 191 | struct spi_message msg; |
189 | 192 | ||
@@ -195,6 +198,12 @@ struct ad7877 { | |||
195 | spinlock_t lock; | 198 | spinlock_t lock; |
196 | struct timer_list timer; /* P: lock */ | 199 | struct timer_list timer; /* P: lock */ |
197 | unsigned pending:1; /* P: lock */ | 200 | unsigned pending:1; /* P: lock */ |
201 | |||
202 | /* | ||
203 | * DMA (thus cache coherency maintenance) requires the | ||
204 | * transfer buffers to live in their own cache lines. | ||
205 | */ | ||
206 | u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned; | ||
198 | }; | 207 | }; |
199 | 208 | ||
200 | static int gpio3; | 209 | static int gpio3; |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439..00000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null | |||
@@ -1,385 +0,0 @@ | |||
1 | /* | ||
2 | * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models | ||
3 | * | ||
4 | * Copyright (c) 2004-2005 Richard Purdie | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | |||
13 | #include <linux/delay.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/irq.h> | ||
21 | |||
22 | #include <mach/sharpsl.h> | ||
23 | #include <mach/hardware.h> | ||
24 | #include <mach/pxa2xx-gpio.h> | ||
25 | |||
26 | |||
27 | #define PWR_MODE_ACTIVE 0 | ||
28 | #define PWR_MODE_SUSPEND 1 | ||
29 | |||
30 | #define X_AXIS_MAX 3830 | ||
31 | #define X_AXIS_MIN 150 | ||
32 | #define Y_AXIS_MAX 3830 | ||
33 | #define Y_AXIS_MIN 190 | ||
34 | #define PRESSURE_MIN 0 | ||
35 | #define PRESSURE_MAX 15000 | ||
36 | |||
37 | struct ts_event { | ||
38 | short pressure; | ||
39 | short x; | ||
40 | short y; | ||
41 | }; | ||
42 | |||
43 | struct corgi_ts { | ||
44 | struct input_dev *input; | ||
45 | struct timer_list timer; | ||
46 | struct ts_event tc; | ||
47 | int pendown; | ||
48 | int power_mode; | ||
49 | int irq_gpio; | ||
50 | struct corgits_machinfo *machinfo; | ||
51 | }; | ||
52 | |||
53 | #ifdef CONFIG_PXA25x | ||
54 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) | ||
55 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) | ||
56 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) | ||
57 | #endif | ||
58 | #ifdef CONFIG_PXA27x | ||
59 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) | ||
60 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) | ||
61 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) | ||
62 | #endif | ||
63 | |||
64 | /* ADS7846 Touch Screen Controller bit definitions */ | ||
65 | #define ADSCTRL_PD0 (1u << 0) /* PD0 */ | ||
66 | #define ADSCTRL_PD1 (1u << 1) /* PD1 */ | ||
67 | #define ADSCTRL_DFR (1u << 2) /* SER/DFR */ | ||
68 | #define ADSCTRL_MOD (1u << 3) /* Mode */ | ||
69 | #define ADSCTRL_ADR_SH 4 /* Address setting */ | ||
70 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ | ||
71 | |||
72 | /* External Functions */ | ||
73 | extern unsigned int get_clk_frequency_khz(int info); | ||
74 | |||
75 | static unsigned long calc_waittime(struct corgi_ts *corgi_ts) | ||
76 | { | ||
77 | unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); | ||
78 | |||
79 | if (hsync_invperiod) | ||
80 | return get_clk_frequency_khz(0)*1000/hsync_invperiod; | ||
81 | else | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, | ||
86 | unsigned int address, unsigned long wait_time) | ||
87 | { | ||
88 | unsigned long timer1 = 0, timer2, pmnc = 0; | ||
89 | int pos = 0; | ||
90 | |||
91 | if (wait_time && doSend) { | ||
92 | PMNC_GET(pmnc); | ||
93 | if (!(pmnc & 0x01)) | ||
94 | PMNC_SET(0x01); | ||
95 | |||
96 | /* polling HSync */ | ||
97 | corgi_ts->machinfo->wait_hsync(); | ||
98 | /* get CCNT */ | ||
99 | CCNT(timer1); | ||
100 | } | ||
101 | |||
102 | if (doRecive) | ||
103 | pos = corgi_ssp_ads7846_get(); | ||
104 | |||
105 | if (doSend) { | ||
106 | int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; | ||
107 | /* dummy command */ | ||
108 | corgi_ssp_ads7846_put(cmd); | ||
109 | corgi_ssp_ads7846_get(); | ||
110 | |||
111 | if (wait_time) { | ||
112 | /* Wait after HSync */ | ||
113 | CCNT(timer2); | ||
114 | if (timer2-timer1 > wait_time) { | ||
115 | /* too slow - timeout, try again */ | ||
116 | corgi_ts->machinfo->wait_hsync(); | ||
117 | /* get CCNT */ | ||
118 | CCNT(timer1); | ||
119 | /* Wait after HSync */ | ||
120 | CCNT(timer2); | ||
121 | } | ||
122 | while (timer2 - timer1 < wait_time) | ||
123 | CCNT(timer2); | ||
124 | } | ||
125 | corgi_ssp_ads7846_put(cmd); | ||
126 | if (wait_time && !(pmnc & 0x01)) | ||
127 | PMNC_SET(pmnc); | ||
128 | } | ||
129 | return pos; | ||
130 | } | ||
131 | |||
132 | static int read_xydata(struct corgi_ts *corgi_ts) | ||
133 | { | ||
134 | unsigned int x, y, z1, z2; | ||
135 | unsigned long flags, wait_time; | ||
136 | |||
137 | /* critical section */ | ||
138 | local_irq_save(flags); | ||
139 | corgi_ssp_ads7846_lock(); | ||
140 | wait_time = calc_waittime(corgi_ts); | ||
141 | |||
142 | /* Y-axis */ | ||
143 | sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); | ||
144 | |||
145 | /* Y-axis */ | ||
146 | sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); | ||
147 | |||
148 | /* X-axis */ | ||
149 | y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); | ||
150 | |||
151 | /* Z1 */ | ||
152 | x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); | ||
153 | |||
154 | /* Z2 */ | ||
155 | z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); | ||
156 | z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); | ||
157 | |||
158 | /* Power-Down Enable */ | ||
159 | corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
160 | corgi_ssp_ads7846_get(); | ||
161 | |||
162 | corgi_ssp_ads7846_unlock(); | ||
163 | local_irq_restore(flags); | ||
164 | |||
165 | if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { | ||
166 | corgi_ts->tc.pressure = 0; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | corgi_ts->tc.x = x; | ||
171 | corgi_ts->tc.y = y; | ||
172 | corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; | ||
173 | return 1; | ||
174 | } | ||
175 | |||
176 | static void new_data(struct corgi_ts *corgi_ts) | ||
177 | { | ||
178 | struct input_dev *dev = corgi_ts->input; | ||
179 | |||
180 | if (corgi_ts->power_mode != PWR_MODE_ACTIVE) | ||
181 | return; | ||
182 | |||
183 | if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) | ||
184 | return; | ||
185 | |||
186 | input_report_abs(dev, ABS_X, corgi_ts->tc.x); | ||
187 | input_report_abs(dev, ABS_Y, corgi_ts->tc.y); | ||
188 | input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); | ||
189 | input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); | ||
190 | input_sync(dev); | ||
191 | } | ||
192 | |||
193 | static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) | ||
194 | { | ||
195 | if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { | ||
196 | /* Disable Interrupt */ | ||
197 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); | ||
198 | if (read_xydata(corgi_ts)) { | ||
199 | corgi_ts->pendown = 1; | ||
200 | new_data(corgi_ts); | ||
201 | } | ||
202 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
203 | } else { | ||
204 | if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { | ||
205 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
206 | corgi_ts->pendown++; | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | if (corgi_ts->pendown) { | ||
211 | corgi_ts->tc.pressure = 0; | ||
212 | new_data(corgi_ts); | ||
213 | } | ||
214 | |||
215 | /* Enable Falling Edge */ | ||
216 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
217 | corgi_ts->pendown = 0; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static void corgi_ts_timer(unsigned long data) | ||
222 | { | ||
223 | struct corgi_ts *corgits_data = (struct corgi_ts *) data; | ||
224 | |||
225 | ts_interrupt_main(corgits_data, 1); | ||
226 | } | ||
227 | |||
228 | static irqreturn_t ts_interrupt(int irq, void *dev_id) | ||
229 | { | ||
230 | struct corgi_ts *corgits_data = dev_id; | ||
231 | |||
232 | ts_interrupt_main(corgits_data, 0); | ||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | #ifdef CONFIG_PM | ||
237 | static int corgits_suspend(struct platform_device *dev, pm_message_t state) | ||
238 | { | ||
239 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
240 | |||
241 | if (corgi_ts->pendown) { | ||
242 | del_timer_sync(&corgi_ts->timer); | ||
243 | corgi_ts->tc.pressure = 0; | ||
244 | new_data(corgi_ts); | ||
245 | corgi_ts->pendown = 0; | ||
246 | } | ||
247 | corgi_ts->power_mode = PWR_MODE_SUSPEND; | ||
248 | |||
249 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int corgits_resume(struct platform_device *dev) | ||
255 | { | ||
256 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
257 | |||
258 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
259 | /* Enable Falling Edge */ | ||
260 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
261 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | #else | ||
266 | #define corgits_suspend NULL | ||
267 | #define corgits_resume NULL | ||
268 | #endif | ||
269 | |||
270 | static int __devinit corgits_probe(struct platform_device *pdev) | ||
271 | { | ||
272 | struct corgi_ts *corgi_ts; | ||
273 | struct input_dev *input_dev; | ||
274 | int err = -ENOMEM; | ||
275 | |||
276 | corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); | ||
277 | input_dev = input_allocate_device(); | ||
278 | if (!corgi_ts || !input_dev) | ||
279 | goto fail1; | ||
280 | |||
281 | platform_set_drvdata(pdev, corgi_ts); | ||
282 | |||
283 | corgi_ts->machinfo = pdev->dev.platform_data; | ||
284 | corgi_ts->irq_gpio = platform_get_irq(pdev, 0); | ||
285 | |||
286 | if (corgi_ts->irq_gpio < 0) { | ||
287 | err = -ENODEV; | ||
288 | goto fail1; | ||
289 | } | ||
290 | |||
291 | corgi_ts->input = input_dev; | ||
292 | |||
293 | init_timer(&corgi_ts->timer); | ||
294 | corgi_ts->timer.data = (unsigned long) corgi_ts; | ||
295 | corgi_ts->timer.function = corgi_ts_timer; | ||
296 | |||
297 | input_dev->name = "Corgi Touchscreen"; | ||
298 | input_dev->phys = "corgits/input0"; | ||
299 | input_dev->id.bustype = BUS_HOST; | ||
300 | input_dev->id.vendor = 0x0001; | ||
301 | input_dev->id.product = 0x0002; | ||
302 | input_dev->id.version = 0x0100; | ||
303 | input_dev->dev.parent = &pdev->dev; | ||
304 | |||
305 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
306 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
307 | input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); | ||
308 | input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); | ||
309 | input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); | ||
310 | |||
311 | pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); | ||
312 | |||
313 | /* Initiaize ADS7846 Difference Reference mode */ | ||
314 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
315 | mdelay(5); | ||
316 | corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
317 | mdelay(5); | ||
318 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
319 | mdelay(5); | ||
320 | corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
321 | mdelay(5); | ||
322 | |||
323 | if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { | ||
324 | err = -EBUSY; | ||
325 | goto fail1; | ||
326 | } | ||
327 | |||
328 | err = input_register_device(corgi_ts->input); | ||
329 | if (err) | ||
330 | goto fail2; | ||
331 | |||
332 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
333 | |||
334 | /* Enable Falling Edge */ | ||
335 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
340 | fail1: input_free_device(input_dev); | ||
341 | kfree(corgi_ts); | ||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static int __devexit corgits_remove(struct platform_device *pdev) | ||
346 | { | ||
347 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); | ||
348 | |||
349 | free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
350 | del_timer_sync(&corgi_ts->timer); | ||
351 | corgi_ts->machinfo->put_hsync(); | ||
352 | input_unregister_device(corgi_ts->input); | ||
353 | kfree(corgi_ts); | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | static struct platform_driver corgits_driver = { | ||
359 | .probe = corgits_probe, | ||
360 | .remove = __devexit_p(corgits_remove), | ||
361 | .suspend = corgits_suspend, | ||
362 | .resume = corgits_resume, | ||
363 | .driver = { | ||
364 | .name = "corgi-ts", | ||
365 | .owner = THIS_MODULE, | ||
366 | }, | ||
367 | }; | ||
368 | |||
369 | static int __init corgits_init(void) | ||
370 | { | ||
371 | return platform_driver_register(&corgits_driver); | ||
372 | } | ||
373 | |||
374 | static void __exit corgits_exit(void) | ||
375 | { | ||
376 | platform_driver_unregister(&corgits_driver); | ||
377 | } | ||
378 | |||
379 | module_init(corgits_init); | ||
380 | module_exit(corgits_exit); | ||
381 | |||
382 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
383 | MODULE_DESCRIPTION("Corgi TouchScreen Driver"); | ||
384 | MODULE_LICENSE("GPL"); | ||
385 | MODULE_ALIAS("platform:corgi-ts"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 204b8a1a601..75f8b73010f 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -124,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id) | |||
124 | return IRQ_HANDLED; | 124 | return IRQ_HANDLED; |
125 | } | 125 | } |
126 | 126 | ||
127 | static int eeti_ts_open(struct input_dev *dev) | 127 | static void eeti_ts_start(struct eeti_ts_priv *priv) |
128 | { | 128 | { |
129 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
130 | |||
131 | enable_irq(priv->irq); | 129 | enable_irq(priv->irq); |
132 | 130 | ||
133 | /* Read the events once to arm the IRQ */ | 131 | /* Read the events once to arm the IRQ */ |
134 | eeti_ts_read(&priv->work); | 132 | eeti_ts_read(&priv->work); |
133 | } | ||
134 | |||
135 | static void eeti_ts_stop(struct eeti_ts_priv *priv) | ||
136 | { | ||
137 | disable_irq(priv->irq); | ||
138 | cancel_work_sync(&priv->work); | ||
139 | } | ||
140 | |||
141 | static int eeti_ts_open(struct input_dev *dev) | ||
142 | { | ||
143 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
144 | |||
145 | eeti_ts_start(priv); | ||
135 | 146 | ||
136 | return 0; | 147 | return 0; |
137 | } | 148 | } |
@@ -140,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev) | |||
140 | { | 151 | { |
141 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | 152 | struct eeti_ts_priv *priv = input_get_drvdata(dev); |
142 | 153 | ||
143 | disable_irq(priv->irq); | 154 | eeti_ts_stop(priv); |
144 | cancel_work_sync(&priv->work); | ||
145 | } | 155 | } |
146 | 156 | ||
147 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 157 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
@@ -153,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
153 | unsigned int irq_flags; | 163 | unsigned int irq_flags; |
154 | int err = -ENOMEM; | 164 | int err = -ENOMEM; |
155 | 165 | ||
156 | /* In contrast to what's described in the datasheet, there seems | 166 | /* |
167 | * In contrast to what's described in the datasheet, there seems | ||
157 | * to be no way of probing the presence of that device using I2C | 168 | * to be no way of probing the presence of that device using I2C |
158 | * commands. So we need to blindly believe it is there, and wait | 169 | * commands. So we need to blindly believe it is there, and wait |
159 | * for interrupts to occur. */ | 170 | * for interrupts to occur. |
171 | */ | ||
160 | 172 | ||
161 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
162 | if (!priv) { | 174 | if (!priv) { |
@@ -212,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
212 | goto err2; | 224 | goto err2; |
213 | } | 225 | } |
214 | 226 | ||
215 | /* Disable the irq for now. It will be enabled once the input device | 227 | /* |
216 | * is opened. */ | 228 | * Disable the device for now. It will be enabled once the |
217 | disable_irq(priv->irq); | 229 | * input device is opened. |
230 | */ | ||
231 | eeti_ts_stop(priv); | ||
218 | 232 | ||
219 | device_init_wakeup(&client->dev, 0); | 233 | device_init_wakeup(&client->dev, 0); |
220 | return 0; | 234 | return 0; |
@@ -235,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
235 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 249 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
236 | 250 | ||
237 | free_irq(priv->irq, priv); | 251 | free_irq(priv->irq, priv); |
252 | /* | ||
253 | * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it | ||
254 | * so that device still works if we reload the driver. | ||
255 | */ | ||
256 | enable_irq(priv->irq); | ||
257 | |||
238 | input_unregister_device(priv->input); | 258 | input_unregister_device(priv->input); |
239 | i2c_set_clientdata(client, NULL); | 259 | i2c_set_clientdata(client, NULL); |
240 | kfree(priv); | 260 | kfree(priv); |
@@ -246,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
246 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 266 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) |
247 | { | 267 | { |
248 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 268 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
269 | struct input_dev *input_dev = priv->input; | ||
270 | |||
271 | mutex_lock(&input_dev->mutex); | ||
272 | |||
273 | if (input_dev->users) | ||
274 | eeti_ts_stop(priv); | ||
275 | |||
276 | mutex_unlock(&input_dev->mutex); | ||
249 | 277 | ||
250 | if (device_may_wakeup(&client->dev)) | 278 | if (device_may_wakeup(&client->dev)) |
251 | enable_irq_wake(priv->irq); | 279 | enable_irq_wake(priv->irq); |
@@ -256,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
256 | static int eeti_ts_resume(struct i2c_client *client) | 284 | static int eeti_ts_resume(struct i2c_client *client) |
257 | { | 285 | { |
258 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 286 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
287 | struct input_dev *input_dev = priv->input; | ||
259 | 288 | ||
260 | if (device_may_wakeup(&client->dev)) | 289 | if (device_may_wakeup(&client->dev)) |
261 | disable_irq_wake(priv->irq); | 290 | disable_irq_wake(priv->irq); |
262 | 291 | ||
292 | mutex_lock(&input_dev->mutex); | ||
293 | |||
294 | if (input_dev->users) | ||
295 | eeti_ts_start(priv); | ||
296 | |||
297 | mutex_unlock(&input_dev->mutex); | ||
298 | |||
263 | return 0; | 299 | return 0; |
264 | } | 300 | } |
265 | #else | 301 | #else |
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c new file mode 100644 index 00000000000..2da6cc31bb2 --- /dev/null +++ b/drivers/input/touchscreen/hampshire.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * Hampshire serial touchscreen driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Adam Bennett | ||
5 | * Based on the dynapro driver (c) Tias Guns | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published by | ||
12 | * the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* | ||
16 | * 2010/04/08 Adam Bennett <abennett72@gmail.com> | ||
17 | * Copied dynapro.c and edited for Hampshire 4-byte protocol | ||
18 | */ | ||
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/serio.h> | ||
26 | #include <linux/init.h> | ||
27 | |||
28 | #define DRIVER_DESC "Hampshire serial touchscreen driver" | ||
29 | |||
30 | MODULE_AUTHOR("Adam Bennett <abennett72@gmail.com>"); | ||
31 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | /* | ||
35 | * Definitions & global arrays. | ||
36 | */ | ||
37 | |||
38 | #define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40 | ||
39 | #define HAMPSHIRE_FORMAT_LENGTH 4 | ||
40 | #define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80 | ||
41 | |||
42 | #define HAMPSHIRE_MIN_XC 0 | ||
43 | #define HAMPSHIRE_MAX_XC 0x1000 | ||
44 | #define HAMPSHIRE_MIN_YC 0 | ||
45 | #define HAMPSHIRE_MAX_YC 0x1000 | ||
46 | |||
47 | #define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6)) | ||
48 | #define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9)) | ||
49 | #define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0]) | ||
50 | |||
51 | /* | ||
52 | * Per-touchscreen data. | ||
53 | */ | ||
54 | |||
55 | struct hampshire { | ||
56 | struct input_dev *dev; | ||
57 | struct serio *serio; | ||
58 | int idx; | ||
59 | unsigned char data[HAMPSHIRE_FORMAT_LENGTH]; | ||
60 | char phys[32]; | ||
61 | }; | ||
62 | |||
63 | static void hampshire_process_data(struct hampshire *phampshire) | ||
64 | { | ||
65 | struct input_dev *dev = phampshire->dev; | ||
66 | |||
67 | if (HAMPSHIRE_FORMAT_LENGTH == ++phampshire->idx) { | ||
68 | input_report_abs(dev, ABS_X, HAMPSHIRE_GET_XC(phampshire->data)); | ||
69 | input_report_abs(dev, ABS_Y, HAMPSHIRE_GET_YC(phampshire->data)); | ||
70 | input_report_key(dev, BTN_TOUCH, | ||
71 | HAMPSHIRE_GET_TOUCHED(phampshire->data)); | ||
72 | input_sync(dev); | ||
73 | |||
74 | phampshire->idx = 0; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | static irqreturn_t hampshire_interrupt(struct serio *serio, | ||
79 | unsigned char data, unsigned int flags) | ||
80 | { | ||
81 | struct hampshire *phampshire = serio_get_drvdata(serio); | ||
82 | |||
83 | phampshire->data[phampshire->idx] = data; | ||
84 | |||
85 | if (HAMPSHIRE_RESPONSE_BEGIN_BYTE & phampshire->data[0]) | ||
86 | hampshire_process_data(phampshire); | ||
87 | else | ||
88 | dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", | ||
89 | phampshire->data[0]); | ||
90 | |||
91 | return IRQ_HANDLED; | ||
92 | } | ||
93 | |||
94 | static void hampshire_disconnect(struct serio *serio) | ||
95 | { | ||
96 | struct hampshire *phampshire = serio_get_drvdata(serio); | ||
97 | |||
98 | input_get_device(phampshire->dev); | ||
99 | input_unregister_device(phampshire->dev); | ||
100 | serio_close(serio); | ||
101 | serio_set_drvdata(serio, NULL); | ||
102 | input_put_device(phampshire->dev); | ||
103 | kfree(phampshire); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * hampshire_connect() is the routine that is called when someone adds a | ||
108 | * new serio device that supports hampshire protocol and registers it as | ||
109 | * an input device. This is usually accomplished using inputattach. | ||
110 | */ | ||
111 | |||
112 | static int hampshire_connect(struct serio *serio, struct serio_driver *drv) | ||
113 | { | ||
114 | struct hampshire *phampshire; | ||
115 | struct input_dev *input_dev; | ||
116 | int err; | ||
117 | |||
118 | phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); | ||
119 | input_dev = input_allocate_device(); | ||
120 | if (!phampshire || !input_dev) { | ||
121 | err = -ENOMEM; | ||
122 | goto fail1; | ||
123 | } | ||
124 | |||
125 | phampshire->serio = serio; | ||
126 | phampshire->dev = input_dev; | ||
127 | snprintf(phampshire->phys, sizeof(phampshire->phys), | ||
128 | "%s/input0", serio->phys); | ||
129 | |||
130 | input_dev->name = "Hampshire Serial TouchScreen"; | ||
131 | input_dev->phys = phampshire->phys; | ||
132 | input_dev->id.bustype = BUS_RS232; | ||
133 | input_dev->id.vendor = SERIO_HAMPSHIRE; | ||
134 | input_dev->id.product = 0; | ||
135 | input_dev->id.version = 0x0001; | ||
136 | input_dev->dev.parent = &serio->dev; | ||
137 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
138 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
139 | input_set_abs_params(phampshire->dev, ABS_X, | ||
140 | HAMPSHIRE_MIN_XC, HAMPSHIRE_MAX_XC, 0, 0); | ||
141 | input_set_abs_params(phampshire->dev, ABS_Y, | ||
142 | HAMPSHIRE_MIN_YC, HAMPSHIRE_MAX_YC, 0, 0); | ||
143 | |||
144 | serio_set_drvdata(serio, phampshire); | ||
145 | |||
146 | err = serio_open(serio, drv); | ||
147 | if (err) | ||
148 | goto fail2; | ||
149 | |||
150 | err = input_register_device(phampshire->dev); | ||
151 | if (err) | ||
152 | goto fail3; | ||
153 | |||
154 | return 0; | ||
155 | |||
156 | fail3: serio_close(serio); | ||
157 | fail2: serio_set_drvdata(serio, NULL); | ||
158 | fail1: input_free_device(input_dev); | ||
159 | kfree(phampshire); | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * The serio driver structure. | ||
165 | */ | ||
166 | |||
167 | static struct serio_device_id hampshire_serio_ids[] = { | ||
168 | { | ||
169 | .type = SERIO_RS232, | ||
170 | .proto = SERIO_HAMPSHIRE, | ||
171 | .id = SERIO_ANY, | ||
172 | .extra = SERIO_ANY, | ||
173 | }, | ||
174 | { 0 } | ||
175 | }; | ||
176 | |||
177 | MODULE_DEVICE_TABLE(serio, hampshire_serio_ids); | ||
178 | |||
179 | static struct serio_driver hampshire_drv = { | ||
180 | .driver = { | ||
181 | .name = "hampshire", | ||
182 | }, | ||
183 | .description = DRIVER_DESC, | ||
184 | .id_table = hampshire_serio_ids, | ||
185 | .interrupt = hampshire_interrupt, | ||
186 | .connect = hampshire_connect, | ||
187 | .disconnect = hampshire_disconnect, | ||
188 | }; | ||
189 | |||
190 | /* | ||
191 | * The functions for inserting/removing us as a module. | ||
192 | */ | ||
193 | |||
194 | static int __init hampshire_init(void) | ||
195 | { | ||
196 | return serio_register_driver(&hampshire_drv); | ||
197 | } | ||
198 | |||
199 | static void __exit hampshire_exit(void) | ||
200 | { | ||
201 | serio_unregister_driver(&hampshire_drv); | ||
202 | } | ||
203 | |||
204 | module_init(hampshire_init); | ||
205 | module_exit(hampshire_exit); | ||
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 98a7d127948..e0b7c834111 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
@@ -37,9 +37,7 @@ | |||
37 | 37 | ||
38 | #include <plat/adc.h> | 38 | #include <plat/adc.h> |
39 | #include <plat/regs-adc.h> | 39 | #include <plat/regs-adc.h> |
40 | 40 | #include <plat/ts.h> | |
41 | #include <mach/regs-gpio.h> | ||
42 | #include <mach/ts.h> | ||
43 | 41 | ||
44 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) | 42 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) |
45 | 43 | ||
@@ -57,6 +55,8 @@ | |||
57 | S3C2410_ADCTSC_AUTO_PST | \ | 55 | S3C2410_ADCTSC_AUTO_PST | \ |
58 | S3C2410_ADCTSC_XY_PST(0)) | 56 | S3C2410_ADCTSC_XY_PST(0)) |
59 | 57 | ||
58 | #define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */ | ||
59 | |||
60 | /* Per-touchscreen data. */ | 60 | /* Per-touchscreen data. */ |
61 | 61 | ||
62 | /** | 62 | /** |
@@ -71,6 +71,7 @@ | |||
71 | * @irq_tc: The interrupt number for pen up/down interrupt | 71 | * @irq_tc: The interrupt number for pen up/down interrupt |
72 | * @count: The number of samples collected. | 72 | * @count: The number of samples collected. |
73 | * @shift: The log2 of the maximum count to read in one go. | 73 | * @shift: The log2 of the maximum count to read in one go. |
74 | * @features: The features supported by the TSADC MOdule. | ||
74 | */ | 75 | */ |
75 | struct s3c2410ts { | 76 | struct s3c2410ts { |
76 | struct s3c_adc_client *client; | 77 | struct s3c_adc_client *client; |
@@ -83,26 +84,12 @@ struct s3c2410ts { | |||
83 | int irq_tc; | 84 | int irq_tc; |
84 | int count; | 85 | int count; |
85 | int shift; | 86 | int shift; |
87 | int features; | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | static struct s3c2410ts ts; | 90 | static struct s3c2410ts ts; |
89 | 91 | ||
90 | /** | 92 | /** |
91 | * s3c2410_ts_connect - configure gpio for s3c2410 systems | ||
92 | * | ||
93 | * Configure the GPIO for the S3C2410 system, where we have external FETs | ||
94 | * connected to the device (later systems such as the S3C2440 integrate | ||
95 | * these into the device). | ||
96 | */ | ||
97 | static inline void s3c2410_ts_connect(void) | ||
98 | { | ||
99 | s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); | ||
100 | s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); | ||
101 | s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); | ||
102 | s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * get_down - return the down state of the pen | 93 | * get_down - return the down state of the pen |
107 | * @data0: The data read from ADCDAT0 register. | 94 | * @data0: The data read from ADCDAT0 register. |
108 | * @data1: The data read from ADCDAT1 register. | 95 | * @data1: The data read from ADCDAT1 register. |
@@ -188,6 +175,11 @@ static irqreturn_t stylus_irq(int irq, void *dev_id) | |||
188 | else | 175 | else |
189 | dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); | 176 | dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); |
190 | 177 | ||
178 | if (ts.features & FEAT_PEN_IRQ) { | ||
179 | /* Clear pen down/up interrupt */ | ||
180 | writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP); | ||
181 | } | ||
182 | |||
191 | return IRQ_HANDLED; | 183 | return IRQ_HANDLED; |
192 | } | 184 | } |
193 | 185 | ||
@@ -296,9 +288,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) | |||
296 | goto err_clk; | 288 | goto err_clk; |
297 | } | 289 | } |
298 | 290 | ||
299 | /* Configure the touchscreen external FETs on the S3C2410 */ | 291 | /* inititalise the gpio */ |
300 | if (!platform_get_device_id(pdev)->driver_data) | 292 | if (info->cfg_gpio) |
301 | s3c2410_ts_connect(); | 293 | info->cfg_gpio(to_platform_device(ts.dev)); |
302 | 294 | ||
303 | ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, | 295 | ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, |
304 | s3c24xx_ts_conversion, 1); | 296 | s3c24xx_ts_conversion, 1); |
@@ -334,6 +326,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) | |||
334 | ts.input->id.version = 0x0102; | 326 | ts.input->id.version = 0x0102; |
335 | 327 | ||
336 | ts.shift = info->oversampling_shift; | 328 | ts.shift = info->oversampling_shift; |
329 | ts.features = platform_get_device_id(pdev)->driver_data; | ||
337 | 330 | ||
338 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, | 331 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, |
339 | "s3c2410_ts_pen", ts.input); | 332 | "s3c2410_ts_pen", ts.input); |
@@ -420,15 +413,14 @@ static struct dev_pm_ops s3c_ts_pmops = { | |||
420 | #endif | 413 | #endif |
421 | 414 | ||
422 | static struct platform_device_id s3cts_driver_ids[] = { | 415 | static struct platform_device_id s3cts_driver_ids[] = { |
423 | { "s3c2410-ts", 0 }, | 416 | { "s3c64xx-ts", FEAT_PEN_IRQ }, |
424 | { "s3c2440-ts", 1 }, | ||
425 | { } | 417 | { } |
426 | }; | 418 | }; |
427 | MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); | 419 | MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); |
428 | 420 | ||
429 | static struct platform_driver s3c_ts_driver = { | 421 | static struct platform_driver s3c_ts_driver = { |
430 | .driver = { | 422 | .driver = { |
431 | .name = "s3c24xx-ts", | 423 | .name = "samsung-ts", |
432 | .owner = THIS_MODULE, | 424 | .owner = THIS_MODULE, |
433 | #ifdef CONFIG_PM | 425 | #ifdef CONFIG_PM |
434 | .pm = &s3c_ts_pmops, | 426 | .pm = &s3c_ts_pmops, |
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index be23780e8a3..769b479fcaa 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -347,6 +347,8 @@ static int __devexit tsc2007_remove(struct i2c_client *client) | |||
347 | struct tsc2007 *ts = i2c_get_clientdata(client); | 347 | struct tsc2007 *ts = i2c_get_clientdata(client); |
348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; | 348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
349 | 349 | ||
350 | i2c_set_clientdata(client, NULL); | ||
351 | |||
350 | tsc2007_free_irq(ts); | 352 | tsc2007_free_irq(ts); |
351 | 353 | ||
352 | if (pdata->exit_platform_hw) | 354 | if (pdata->exit_platform_hw) |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 99330bbdbac..29a8bbf3f08 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -811,12 +811,11 @@ static int nexio_init(struct usbtouch_usb *usbtouch) | |||
811 | 811 | ||
812 | priv = usbtouch->priv; | 812 | priv = usbtouch->priv; |
813 | 813 | ||
814 | priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL); | 814 | priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), |
815 | GFP_KERNEL); | ||
815 | if (!priv->ack_buf) | 816 | if (!priv->ack_buf) |
816 | goto err_priv; | 817 | goto err_priv; |
817 | 818 | ||
818 | memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt)); | ||
819 | |||
820 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); | 819 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); |
821 | if (!priv->ack) { | 820 | if (!priv->ack) { |
822 | dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); | 821 | dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); |
@@ -1291,8 +1290,8 @@ static void usbtouch_close(struct input_dev *input) | |||
1291 | static void usbtouch_free_buffers(struct usb_device *udev, | 1290 | static void usbtouch_free_buffers(struct usb_device *udev, |
1292 | struct usbtouch_usb *usbtouch) | 1291 | struct usbtouch_usb *usbtouch) |
1293 | { | 1292 | { |
1294 | usb_buffer_free(udev, usbtouch->type->rept_size, | 1293 | usb_free_coherent(udev, usbtouch->type->rept_size, |
1295 | usbtouch->data, usbtouch->data_dma); | 1294 | usbtouch->data, usbtouch->data_dma); |
1296 | kfree(usbtouch->buffer); | 1295 | kfree(usbtouch->buffer); |
1297 | } | 1296 | } |
1298 | 1297 | ||
@@ -1336,8 +1335,8 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
1336 | if (!type->process_pkt) | 1335 | if (!type->process_pkt) |
1337 | type->process_pkt = usbtouch_process_pkt; | 1336 | type->process_pkt = usbtouch_process_pkt; |
1338 | 1337 | ||
1339 | usbtouch->data = usb_buffer_alloc(udev, type->rept_size, | 1338 | usbtouch->data = usb_alloc_coherent(udev, type->rept_size, |
1340 | GFP_KERNEL, &usbtouch->data_dma); | 1339 | GFP_KERNEL, &usbtouch->data_dma); |
1341 | if (!usbtouch->data) | 1340 | if (!usbtouch->data) |
1342 | goto out_free; | 1341 | goto out_free; |
1343 | 1342 | ||
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index 5109bf3dd85..cbfef1ea7e3 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -200,7 +200,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, | |||
200 | mutex_lock(&wm->codec_mutex); | 200 | mutex_lock(&wm->codec_mutex); |
201 | reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); | 201 | reg = wm97xx_reg_read(wm, AC97_GPIO_STATUS); |
202 | 202 | ||
203 | if (status & WM97XX_GPIO_HIGH) | 203 | if (status == WM97XX_GPIO_HIGH) |
204 | reg |= gpio; | 204 | reg |= gpio; |
205 | else | 205 | else |
206 | reg &= ~gpio; | 206 | reg &= ~gpio; |