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 7e18bcf05a66..46239e47a260 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 c52bec4d0530..423e0e6031ab 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 1c0b529c06aa..4afe0a3b4884 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 b1edd778639c..405febd94f24 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 b41303d3ec54..6c96631ae5d9 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 9b3353b404da..c1087ce4cef9 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 64c102355f53..d8fa5d724c57 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 706c6b5ed5f4..4596d0c6f922 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 634af6a8e6b3..000000000000 --- 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 60ac4684f875..bc696931fed7 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 13967422658c..000000000000 --- 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 000000000000..493c93f25e2a --- /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 3910f269cfc8..000000000000 --- 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 40dabd8487b5..4cc82826ea6b 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 23140a3bb8e0..48cdabec372a 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 7e95a5d474dc..f9f577031e06 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 000000000000..e9adbe49f6a4 --- /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 000000000000..7f8dedfd1bfe --- /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 000000000000..0fe27baf5e72 --- /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 000000000000..45c54fb13f07 --- /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 614b65d78fe9..bce57129afba 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 2124b99378bb..e148749b5851 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 86457feccfc4..2b0eba6619bd 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 86afdd1fdf9d..a93c525475c6 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 000000000000..5c3ac4e0b055 --- /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 ea4e1fd12651..f080dd31499b 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 668913d12044..bf170f6b4422 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 04d5a4a3181f..4dac8b79fcd4 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 93a22ac0f88c..41201c6b5e68 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 c714ca2407f8..eeb58c1cac16 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 0d22cb9ce42e..99d58764ef03 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 53ec7ddd1826..05edd75abca0 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 b89879bd860f..6dedded27222 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 a138b5da79f9..b18862b2a70e 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 feac5f7af966..ac57bde1bb9f 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 08d66d820d2b..1d2205b24800 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 543c240a85f2..c9983aee9082 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 d8c0c8d6992c..979c50215282 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 e053bdd137ff..593e910bfc7a 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 026df6010161..40cea334ad13 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 f0f40a331dc8..7d4d5e12c0df 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 7e319d65ec57..f34f1dbeb577 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 bf945f789d05..84c80bf7185e 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 000000000000..8f1770e1e08b --- /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 ead0494721d0..6168469ad1a6 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 670c61c5a516..aea9a9399a36 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 4be039d7dcad..51b80b08d467 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 866a9ee1af1a..8ea6afe2e992 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 6682b17bf844..290f4e57b589 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 8fef1b689c69..284dfaab6b8c 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 f46502589e4e..2dc0c07c0469 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 4a852d815c68..847fd0135bcf 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 b50cf04e61a8..063f1af3204f 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 8a8fa4d2d6a8..b9f58ca82fd1 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 7fef7d5cca23..8ad36eef90a2 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 e019d53d1ab4..0d2d7e54b465 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 94a1919d439d..000000000000 --- 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 204b8a1a601c..75f8b73010fa 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 000000000000..2da6cc31bb21 --- /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 98a7d1279486..e0b7c834111d 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 be23780e8a3e..769b479fcaa6 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 99330bbdbac7..29a8bbf3f086 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 5109bf3dd858..cbfef1ea7e30 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; |
