Browse Source

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (64 commits)
  Input: tc3589x-keypad - add missing kerneldoc
  Input: ucb1400-ts - switch to using dev_xxx() for diagnostic messages
  Input: ucb1400_ts - convert to threaded IRQ
  Input: ucb1400_ts - drop inline annotations
  Input: usb1400_ts - add __devinit/__devexit section annotations
  Input: ucb1400_ts - set driver owner
  Input: ucb1400_ts - convert to use dev_pm_ops
  Input: psmouse - make sure we do not use stale methods
  Input: evdev - do not block waiting for an event if fd is nonblock
  Input: evdev - if no events and non-block, return EAGAIN not 0
  Input: evdev - only allow reading events if a full packet is present
  Input: add driver for pixcir i2c touchscreens
  Input: samsung-keypad - implement runtime power management support
  Input: tegra-kbc - report wakeup key for some platforms
  Input: tegra-kbc - add device tree bindings
  Input: add driver for AUO In-Cell touchscreens using pixcir ICs
  Input: mpu3050 - configure the sampling method
  Input: mpu3050 - ensure we enable interrupts
  Input: mpu3050 - add of_match table for device-tree probing
  Input: sentelic - document the latest hardware
  ...

Fix up fairly trivial conflicts (device tree matching conflicting with
some independent cleanups) in drivers/input/keyboard/samsung-keypad.c
Linus Torvalds 13 years ago
parent
commit
dbe950f201
100 changed files with 3840 additions and 1199 deletions
  1. 9 8
      Documentation/ABI/testing/sysfs-driver-wacom
  2. 18 0
      Documentation/devicetree/bindings/input/tegra-kbc.txt
  3. 188 0
      Documentation/input/alps.txt
  4. 103 0
      Documentation/input/gpio-tilt.txt
  5. 333 31
      Documentation/input/sentelic.txt
  6. 1 0
      arch/arm/mach-tegra/include/mach/kbc.h
  7. 1 26
      arch/arm/plat-samsung/include/plat/keypad.h
  8. 11 9
      drivers/input/evdev.c
  9. 5 3
      drivers/input/input-polldev.c
  10. 19 2
      drivers/input/keyboard/Kconfig
  11. 1 0
      drivers/input/keyboard/Makefile
  12. 1 12
      drivers/input/keyboard/adp5520-keys.c
  13. 1 14
      drivers/input/keyboard/amikbd.c
  14. 30 10
      drivers/input/keyboard/atkbd.c
  15. 2 14
      drivers/input/keyboard/bf54x-keys.c
  16. 1 12
      drivers/input/keyboard/davinci_keyscan.c
  17. 1 13
      drivers/input/keyboard/ep93xx_keypad.c
  18. 1 13
      drivers/input/keyboard/gpio_keys_polled.c
  19. 1 13
      drivers/input/keyboard/imx_keypad.c
  20. 1 13
      drivers/input/keyboard/jornada680_kbd.c
  21. 1 13
      drivers/input/keyboard/jornada720_kbd.c
  22. 5 6
      drivers/input/keyboard/lm8323.c
  23. 1 13
      drivers/input/keyboard/matrix_keypad.c
  24. 2 13
      drivers/input/keyboard/nomadik-ske-keypad.c
  25. 1 14
      drivers/input/keyboard/omap-keypad.c
  26. 1 12
      drivers/input/keyboard/omap4-keypad.c
  27. 1 12
      drivers/input/keyboard/opencores-kbd.c
  28. 1 12
      drivers/input/keyboard/pmic8xxx-keypad.c
  29. 1 13
      drivers/input/keyboard/pxa27x_keypad.c
  30. 1 12
      drivers/input/keyboard/pxa930_rotary.c
  31. 82 26
      drivers/input/keyboard/samsung-keypad.c
  32. 1 13
      drivers/input/keyboard/sh_keysc.c
  33. 1 12
      drivers/input/keyboard/spear-keyboard.c
  34. 1 12
      drivers/input/keyboard/stmpe-keypad.c
  35. 3 12
      drivers/input/keyboard/tc3589x-keypad.c
  36. 430 0
      drivers/input/keyboard/tca8418_keypad.c
  37. 109 23
      drivers/input/keyboard/tegra-kbc.c
  38. 1 13
      drivers/input/keyboard/tnetv107x-keypad.c
  39. 1 12
      drivers/input/keyboard/twl4030_keypad.c
  40. 1 13
      drivers/input/keyboard/w90p910_keypad.c
  41. 1 12
      drivers/input/misc/88pm860x_onkey.c
  42. 25 0
      drivers/input/misc/Kconfig
  43. 2 0
      drivers/input/misc/Makefile
  44. 1 12
      drivers/input/misc/ab8500-ponkey.c
  45. 0 1
      drivers/input/misc/adxl34x-spi.c
  46. 8 8
      drivers/input/misc/adxl34x.c
  47. 11 8
      drivers/input/misc/ati_remote2.c
  48. 1 12
      drivers/input/misc/bfin_rotary.c
  49. 1 13
      drivers/input/misc/cobalt_btns.c
  50. 1 12
      drivers/input/misc/dm355evm_keys.c
  51. 299 0
      drivers/input/misc/gp2ap002a00f.c
  52. 213 0
      drivers/input/misc/gpio_tilt_polled.c
  53. 1 12
      drivers/input/misc/ixp4xx-beeper.c
  54. 1 12
      drivers/input/misc/max8925_onkey.c
  55. 2 12
      drivers/input/misc/mc13783-pwrbutton.c
  56. 122 6
      drivers/input/misc/mpu3050.c
  57. 1 13
      drivers/input/misc/pcap_keys.c
  58. 1 12
      drivers/input/misc/pcf50633-input.c
  59. 1 13
      drivers/input/misc/pcspkr.c
  60. 1 12
      drivers/input/misc/pm8xxx-vibrator.c
  61. 1 12
      drivers/input/misc/pmic8xxx-pwrkey.c
  62. 1 12
      drivers/input/misc/pwm-beeper.c
  63. 1 13
      drivers/input/misc/rb532_button.c
  64. 1 13
      drivers/input/misc/rotary_encoder.c
  65. 1 12
      drivers/input/misc/sgi_btns.c
  66. 2 13
      drivers/input/misc/twl4030-pwrbutton.c
  67. 1 13
      drivers/input/misc/twl4030-vibra.c
  68. 1 12
      drivers/input/misc/twl6040-vibra.c
  69. 1 12
      drivers/input/misc/wm831x-on.c
  70. 929 78
      drivers/input/mouse/alps.c
  71. 19 0
      drivers/input/mouse/alps.h
  72. 2 14
      drivers/input/mouse/amimouse.c
  73. 67 13
      drivers/input/mouse/elantech.c
  74. 2 0
      drivers/input/mouse/elantech.h
  75. 1 12
      drivers/input/mouse/gpio_mouse.c
  76. 12 6
      drivers/input/mouse/hgpk.c
  77. 7 2
      drivers/input/mouse/logips2pp.c
  78. 147 82
      drivers/input/mouse/psmouse-base.c
  79. 3 0
      drivers/input/mouse/psmouse.h
  80. 1 13
      drivers/input/mouse/pxa930_trkball.c
  81. 32 11
      drivers/input/mouse/sentelic.c
  82. 142 55
      drivers/input/mouse/synaptics.c
  83. 5 0
      drivers/input/mouse/synaptics.h
  84. 12 5
      drivers/input/mouse/trackpoint.c
  85. 1 12
      drivers/input/serio/altera_ps2.c
  86. 1 13
      drivers/input/serio/at32psif.c
  87. 15 8
      drivers/input/serio/i8042.c
  88. 1 13
      drivers/input/serio/rpckbd.c
  89. 1 13
      drivers/input/serio/xilinx_ps2.c
  90. 19 15
      drivers/input/tablet/aiptek.c
  91. 91 10
      drivers/input/tablet/wacom_sys.c
  92. 176 11
      drivers/input/tablet/wacom_wac.c
  93. 4 1
      drivers/input/tablet/wacom_wac.h
  94. 1 12
      drivers/input/touchscreen/88pm860x-ts.c
  95. 41 0
      drivers/input/touchscreen/Kconfig
  96. 3 0
      drivers/input/touchscreen/Makefile
  97. 8 9
      drivers/input/touchscreen/ad7877.c
  98. 3 28
      drivers/input/touchscreen/ad7879-i2c.c
  99. 1 26
      drivers/input/touchscreen/ad7879-spi.c
  100. 17 6
      drivers/input/touchscreen/ad7879.c

+ 9 - 8
Documentation/ABI/testing/sysfs-driver-wacom

@@ -15,9 +15,9 @@ Contact:	linux-input@vger.kernel.org
 Description:
 Description:
 		Attribute group for control of the status LEDs and the OLEDs.
 		Attribute group for control of the status LEDs and the OLEDs.
 		This attribute group is only available for Intuos 4 M, L,
 		This attribute group is only available for Intuos 4 M, L,
-		and XL (with LEDs and OLEDs) and Cintiq 21UX2 (LEDs only).
-		Therefore its presence implicitly signifies the presence of
-		said LEDs and OLEDs on the tablet device.
+		and XL (with LEDs and OLEDs) and Cintiq 21UX2 and Cintiq 24HD
+		(LEDs only). Therefore its presence implicitly signifies the
+		presence of said LEDs and OLEDs on the tablet device.
 
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status0_luminance
 Date:		August 2011
 Date:		August 2011
@@ -41,16 +41,17 @@ Date:		August 2011
 Contact:	linux-input@vger.kernel.org
 Contact:	linux-input@vger.kernel.org
 Description:
 Description:
 		Writing to this file sets which one of the four (for Intuos 4)
 		Writing to this file sets which one of the four (for Intuos 4)
-		or of the right four (for Cintiq 21UX2) status LEDs is active (0..3).
-		The other three LEDs on the same side are always inactive.
+		or of the right four (for Cintiq 21UX2 and Cintiq 24HD) status
+		LEDs is active (0..3). The other three LEDs on the same side are
+		always inactive.
 
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/status_led1_select
 Date:		September 2011
 Date:		September 2011
 Contact:	linux-input@vger.kernel.org
 Contact:	linux-input@vger.kernel.org
 Description:
 Description:
-		Writing to this file sets which one of the left four (for Cintiq 21UX2)
-		status LEDs is active (0..3). The other three LEDs on the left are always
-		inactive.
+		Writing to this file sets which one of the left four (for Cintiq 21UX2
+		and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on
+		the left are always inactive.
 
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<cfg>.<intf>/wacom_led/buttons_luminance
 Date:		August 2011
 Date:		August 2011

+ 18 - 0
Documentation/devicetree/bindings/input/tegra-kbc.txt

@@ -0,0 +1,18 @@
+* Tegra keyboard controller
+
+Required properties:
+- compatible: "nvidia,tegra20-kbc"
+
+Optional properties:
+- debounce-delay: delay in milliseconds per row scan for debouncing
+- repeat-delay: delay in milliseconds before repeat starts
+- ghost-filter: enable ghost filtering for this device
+- wakeup-source: configure keyboard as a wakeup source for suspend/resume
+
+Example:
+
+keyboard: keyboard {
+	compatible = "nvidia,tegra20-kbc";
+	reg = <0x7000e200 0x100>;
+	ghost-filter;
+};

+ 188 - 0
Documentation/input/alps.txt

@@ -0,0 +1,188 @@
+ALPS Touchpad Protocol
+----------------------
+
+Introduction
+------------
+
+Currently the ALPS touchpad driver supports four protocol versions in use by
+ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various
+protocol versions is contained in the following sections.
+
+Detection
+---------
+
+All ALPS touchpads should respond to the "E6 report" command sequence:
+E8-E6-E6-E6-E9. An ALPS touchpad should respond with either 00-00-0A or
+00-00-64.
+
+If the E6 report is successful, the touchpad model is identified using the "E7
+report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is
+matched against known models in the alps_model_data_array.
+
+With protocol versions 3 and 4, the E7 report model signature is always
+73-02-64. To differentiate between these versions, the response from the
+"Enter Command Mode" sequence must be inspected as described below.
+
+Command Mode
+------------
+
+Protocol versions 3 and 4 have a command mode that is used to read and write
+one-byte device registers in a 16-bit address space. The command sequence
+EC-EC-EC-E9 places the device in command mode, and the device will respond
+with 88-07 followed by a third byte. This third byte can be used to determine
+whether the devices uses the version 3 or 4 protocol.
+
+To exit command mode, PSMOUSE_CMD_SETSTREAM (EA) is sent to the touchpad.
+
+While in command mode, register addresses can be set by first sending a
+specific command, either EC for v3 devices or F5 for v4 devices. Then the
+address is sent one nibble at a time, where each nibble is encoded as a
+command with optional data. This enoding differs slightly between the v3 and
+v4 protocols.
+
+Once an address has been set, the addressed register can be read by sending
+PSMOUSE_CMD_GETINFO (E9). The first two bytes of the response contains the
+address of the register being read, and the third contains the value of the
+register. Registers are written by writing the value one nibble at a time
+using the same encoding used for addresses.
+
+Packet Format
+-------------
+
+In the following tables, the following notation is used.
+
+ CAPITALS = stick, miniscules = touchpad
+
+?'s can have different meanings on different models, such as wheel rotation,
+extra buttons, stick buttons on a dualpoint, etc.
+
+PS/2 packet format
+------------------
+
+ byte 0:  0    0 YSGN XSGN    1    M    R    L
+ byte 1: X7   X6   X5   X4   X3   X2   X1   X0
+ byte 2: Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+
+Note that the device never signals overflow condition.
+
+ALPS Absolute Mode - Protocol Verion 1
+--------------------------------------
+
+ byte 0:  1    0    0    0    1   x9   x8   x7
+ byte 1:  0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:  0    ?    ?    l    r    ?  fin  ges
+ byte 3:  0    ?    ?    ?    ?   y9   y8   y7
+ byte 4:  0   y6   y5   y4   y3   y2   y1   y0
+ byte 5:  0   z6   z5   z4   z3   z2   z1   z0
+
+ALPS Absolute Mode - Protocol Version 2
+---------------------------------------
+
+ byte 0:  1    ?    ?    ?    1    ?    ?    ?
+ byte 1:  0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:  0  x10   x9   x8   x7    ?  fin  ges
+ byte 3:  0   y9   y8   y7    1    M    R    L
+ byte 4:  0   y6   y5   y4   y3   y2   y1   y0
+ byte 5:  0   z6   z5   z4   z3   z2   z1   z0
+
+Dualpoint device -- interleaved packet format
+---------------------------------------------
+
+ byte 0:    1    1    0    0    1    1    1    1
+ byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:    0  x10   x9   x8   x7    0  fin  ges
+ byte 3:    0    0 YSGN XSGN    1    1    1    1
+ byte 4:   X7   X6   X5   X4   X3   X2   X1   X0
+ byte 5:   Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+ byte 6:    0   y9   y8   y7    1    m    r    l
+ byte 7:    0   y6   y5   y4   y3   y2   y1   y0
+ byte 8:    0   z6   z5   z4   z3   z2   z1   z0
+
+ALPS Absolute Mode - Protocol Version 3
+---------------------------------------
+
+ALPS protocol version 3 has three different packet formats. The first two are
+associated with touchpad events, and the third is associatd with trackstick
+events.
+
+The first type is the touchpad position packet.
+
+ byte 0:    1    ?   x1   x0    1    1    1    1
+ byte 1:    0  x10   x9   x8   x7   x6   x5   x4
+ byte 2:    0  y10   y9   y8   y7   y6   y5   y4
+ byte 3:    0    M    R    L    1    m    r    l
+ byte 4:    0   mt   x3   x2   y3   y2   y1   y0
+ byte 5:    0   z6   z5   z4   z3   z2   z1   z0
+
+Note that for some devices the trackstick buttons are reported in this packet,
+and on others it is reported in the trackstick packets.
+
+The second packet type contains bitmaps representing the x and y axes. In the
+bitmaps a given bit is set if there is a finger covering that position on the
+given axis. Thus the bitmap packet can be used for low-resolution multi-touch
+data, although finger tracking is not possible.  This packet also encodes the
+number of contacts (f1 and f0 in the table below).
+
+ byte 0:    1    1   x1   x0    1    1    1    1
+ byte 1:    0   x8   x7   x6   x5   x4   x3   x2
+ byte 2:    0   y7   y6   y5   y4   y3   y2   y1
+ byte 3:    0  y10   y9   y8    1    1    1    1
+ byte 4:    0  x14  x13  x12  x11  x10   x9   y0
+ byte 5:    0    1    ?    ?    ?    ?   f1   f0
+
+This packet only appears after a position packet with the mt bit set, and
+ususally only appears when there are two or more contacts (although
+ocassionally it's seen with only a single contact).
+
+The final v3 packet type is the trackstick packet.
+
+ byte 0:    1    1   x7   y7    1    1    1    1
+ byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:    0   y6   y5   y4   y3   y2   y1   y0
+ byte 3:    0    1    0    0    1    0    0    0
+ byte 4:    0   z4   z3   z2   z1   z0    ?    ?
+ byte 5:    0    0    1    1    1    1    1    1
+
+ALPS Absolute Mode - Protocol Version 4
+---------------------------------------
+
+Protocol version 4 has an 8-byte packet format.
+
+ byte 0:    1    ?   x1   x0    1    1    1    1
+ byte 1:    0  x10   x9   x8   x7   x6   x5   x4
+ byte 2:    0  y10   y9   y8   y7   y6   y5   y4
+ byte 3:    0    1   x3   x2   y3   y2   y1   y0
+ byte 4:    0    ?    ?    ?    1    ?    r    l
+ byte 5:    0   z6   z5   z4   z3   z2   z1   z0
+ byte 6:    bitmap data (described below)
+ byte 7:    bitmap data (described below)
+
+The last two bytes represent a partial bitmap packet, with 3 full packets
+required to construct a complete bitmap packet.  Once assembled, the 6-byte
+bitmap packet has the following format:
+
+ byte 0:    0    1   x7   x6   x5   x4   x3   x2
+ byte 1:    0   x1   x0   y4   y3   y2   y1   y0
+ byte 2:    0    0    ?  x14  x13  x12  x11  x10
+ byte 3:    0   x9   x8   y9   y8   y7   y6   y5
+ byte 4:    0    0    0    0    0    0    0    0
+ byte 5:    0    0    0    0    0    0    0  y10
+
+There are several things worth noting here.
+
+ 1) In the bitmap data, bit 6 of byte 0 serves as a sync byte to
+    identify the first fragment of a bitmap packet.
+
+ 2) The bitmaps represent the same data as in the v3 bitmap packets, although
+    the packet layout is different.
+
+ 3) There doesn't seem to be a count of the contact points anywhere in the v4
+    protocol packets. Deriving a count of contact points must be done by
+    analyzing the bitmaps.
+
+ 4) There is a 3 to 1 ratio of position packets to bitmap packets. Therefore
+    MT position can only be updated for every third ST position update, and
+    the count of contact points can only be updated every third packet as
+    well.
+
+So far no v4 devices with tracksticks have been encountered.

+ 103 - 0
Documentation/input/gpio-tilt.txt

@@ -0,0 +1,103 @@
+Driver for tilt-switches connected via GPIOs
+============================================
+
+Generic driver to read data from tilt switches connected via gpios.
+Orientation can be provided by one or more than one tilt switches,
+i.e. each tilt switch providing one axis, and the number of axes
+is also not limited.
+
+
+Data structures:
+----------------
+
+The array of struct gpio in the gpios field is used to list the gpios
+that represent the current tilt state.
+
+The array of struct gpio_tilt_axis describes the axes that are reported
+to the input system. The values set therein are used for the
+input_set_abs_params calls needed to init the axes.
+
+The array of struct gpio_tilt_state maps gpio states to the corresponding
+values to report. The gpio state is represented as a bitfield where the
+bit-index corresponds to the index of the gpio in the struct gpio array.
+In the same manner the values stored in the axes array correspond to
+the elements of the gpio_tilt_axis-array.
+
+
+Example:
+--------
+
+Example configuration for a single TS1003 tilt switch that rotates around
+one axis in 4 steps and emitts the current tilt via two GPIOs.
+
+static int sg060_tilt_enable(struct device *dev) {
+	/* code to enable the sensors */
+};
+
+static void sg060_tilt_disable(struct device *dev) {
+	/* code to disable the sensors */
+};
+
+static struct gpio sg060_tilt_gpios[] = {
+	{ SG060_TILT_GPIO_SENSOR1, GPIOF_IN, "tilt_sensor1" },
+	{ SG060_TILT_GPIO_SENSOR2, GPIOF_IN, "tilt_sensor2" },
+};
+
+static struct gpio_tilt_state sg060_tilt_states[] = {
+	{
+		.gpios = (0 << 1) | (0 << 0),
+		.axes = (int[]) {
+			0,
+		},
+	}, {
+		.gpios = (0 << 1) | (1 << 0),
+		.axes = (int[]) {
+			1, /* 90 degrees */
+		},
+	}, {
+		.gpios = (1 << 1) | (1 << 0),
+		.axes = (int[]) {
+			2, /* 180 degrees */
+		},
+	}, {
+		.gpios = (1 << 1) | (0 << 0),
+		.axes = (int[]) {
+			3, /* 270 degrees */
+		},
+	},
+};
+
+static struct gpio_tilt_axis sg060_tilt_axes[] = {
+	{
+		.axis = ABS_RY,
+		.min = 0,
+		.max = 3,
+		.fuzz = 0,
+		.flat = 0,
+	},
+};
+
+static struct gpio_tilt_platform_data sg060_tilt_pdata= {
+	.gpios = sg060_tilt_gpios,
+	.nr_gpios = ARRAY_SIZE(sg060_tilt_gpios),
+
+	.axes = sg060_tilt_axes,
+	.nr_axes = ARRAY_SIZE(sg060_tilt_axes),
+
+	.states = sg060_tilt_states,
+	.nr_states = ARRAY_SIZE(sg060_tilt_states),
+
+	.debounce_interval = 100,
+
+	.poll_interval = 1000,
+	.enable = sg060_tilt_enable,
+	.disable = sg060_tilt_disable,
+};
+
+static struct platform_device sg060_device_tilt = {
+	.name = "gpio-tilt-polled",
+	.id = -1,
+	.dev = {
+		.platform_data = &sg060_tilt_pdata,
+	},
+};

+ 333 - 31
Documentation/input/sentelic.txt

@@ -1,5 +1,5 @@
-Copyright (C) 2002-2010 Sentelic Corporation.
-Last update: Jan-13-2010
+Copyright (C) 2002-2011 Sentelic Corporation.
+Last update: Dec-07-2011
 
 
 ==============================================================================
 ==============================================================================
 * Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons)
 * Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons)
@@ -140,6 +140,7 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordination packet
                   => 01, Absolute coordination packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
                 When both fingers are up, the last two reports have zero valid
                 When both fingers are up, the last two reports have zero valid
                 bit.
                 bit.
@@ -164,6 +165,7 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordinates packet
                   => 01, Absolute coordinates packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
                 When both fingers are up, the last two reports have zero valid
                 When both fingers are up, the last two reports have zero valid
                 bit.
                 bit.
@@ -188,6 +190,7 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordinates packet
                   => 01, Absolute coordinates packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => 1
         Bit5 => 1
         Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
         Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
                 0: left button is generated by the on-pad command
                 0: left button is generated by the on-pad command
@@ -205,7 +208,7 @@ Byte 4: Bit7 => scroll right button
         Bit6 => scroll left button
         Bit6 => scroll left button
         Bit5 => scroll down button
         Bit5 => scroll down button
         Bit4 => scroll up button
         Bit4 => scroll up button
-            * Note that if gesture and additional buttoni (Bit4~Bit7)
+            * Note that if gesture and additional button (Bit4~Bit7)
               happen at the same time, the button information will not
               happen at the same time, the button information will not
               be sent.
               be sent.
         Bit3~Bit0 => Reserved
         Bit3~Bit0 => Reserved
@@ -227,6 +230,7 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordinates packet
                   => 01, Absolute coordinates packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
                 When both fingers are up, the last two reports have zero valid
                 When both fingers are up, the last two reports have zero valid
                 bit.
                 bit.
@@ -253,6 +257,7 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordination packet
                   => 01, Absolute coordination packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
         Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
                 When both fingers are up, the last two reports have zero valid
                 When both fingers are up, the last two reports have zero valid
                 bit.
                 bit.
@@ -279,8 +284,9 @@ BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------
 Byte 1: Bit7~Bit6 => 00, Normal data packet
 Byte 1: Bit7~Bit6 => 00, Normal data packet
                   => 01, Absolute coordination packet
                   => 01, Absolute coordination packet
                   => 10, Notify packet
                   => 10, Notify packet
+                  => 11, Normal data packet with on-pad click
         Bit5 => 1
         Bit5 => 1
-        Bit4 => when in absolute coordinate mode (valid when EN_PKT_GO is 1):
+        Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
                 0: left button is generated by the on-pad command
                 0: left button is generated by the on-pad command
                 1: left button is generated by the external button
                 1: left button is generated by the external button
         Bit3 => 1
         Bit3 => 1
@@ -306,6 +312,110 @@ Sample sequence of Multi-finger, Multi-coordinate mode:
 	notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
 	notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
 	abs pkt 2, ..., notify packet (valid bit == 0)
 	abs pkt 2, ..., notify packet (valid bit == 0)
 
 
+==============================================================================
+* Absolute position for STL3888-Cx and STL3888-Dx.
+==============================================================================
+Single Finger, Absolute Coordinate Mode (SFAC)
+   Bit 7 6 5 4 3 2 1 0       7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0
+BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
+  1   |0|1|0|P|1|M|R|L|  2  |X|X|X|X|X|X|X|X|  3 |Y|Y|Y|Y|Y|Y|Y|Y|  4 |r|l|B|F|X|X|Y|Y|
+      |---------------|     |---------------|    |---------------|    |---------------|
+
+Byte 1: Bit7~Bit6 => 00, Normal data packet
+                  => 01, Absolute coordinates packet
+                  => 10, Notify packet
+	Bit5 => Coordinate mode(always 0 in SFAC mode):
+		0: single-finger absolute coordinates (SFAC) mode
+		1: multi-finger, multiple coordinates (MFMC) mode
+	Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
+		1: The LEFT button is generated by external button
+		Default is 1 even if the LEFT button is not pressed.
+	Bit3 => Always 1, as specified by PS/2 protocol.
+	Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
+	Bit1 => Right Button, 1 is pressed, 0 is not pressed.
+	Bit0 => Left Button, 1 is pressed, 0 is not pressed.
+Byte 2: X coordinate (xpos[9:2])
+Byte 3: Y coordinate (ypos[9:2])
+Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
+	Bit3~Bit2 => X coordinate (ypos[1:0])
+	Bit4 => 4th mouse button(forward one page)
+	Bit5 => 5th mouse button(backward one page)
+	Bit6 => scroll left button
+	Bit7 => scroll right button
+
+Multi Finger, Multiple Coordinates Mode (MFMC):
+   Bit 7 6 5 4 3 2 1 0       7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0
+BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
+  1   |0|1|1|P|1|F|R|L|  2  |X|X|X|X|X|X|X|X|  3 |Y|Y|Y|Y|Y|Y|Y|Y|  4 |r|l|B|F|X|X|Y|Y|
+      |---------------|     |---------------|    |---------------|    |---------------|
+
+Byte 1: Bit7~Bit6 => 00, Normal data packet
+                  => 01, Absolute coordination packet
+                  => 10, Notify packet
+	Bit5 => Coordinate mode (always 1 in MFMC mode):
+		0: single-finger absolute coordinates (SFAC) mode
+		1: multi-finger, multiple coordinates (MFMC) mode
+	Bit4 => 0: The LEFT button is generated by on-pad command (OPC)
+		1: The LEFT button is generated by external button
+		Default is 1 even if the LEFT button is not pressed.
+	Bit3 => Always 1, as specified by PS/2 protocol.
+	Bit2 => Finger index, 0 is the first finger, 1 is the second finger.
+		If bit 1 and 0 are all 1 and bit 4 is 0, the middle external
+		button is pressed.
+	Bit1 => Right Button, 1 is pressed, 0 is not pressed.
+	Bit0 => Left Button, 1 is pressed, 0 is not pressed.
+Byte 2: X coordinate (xpos[9:2])
+Byte 3: Y coordinate (ypos[9:2])
+Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
+	Bit3~Bit2 => X coordinate (ypos[1:0])
+	Bit4 => 4th mouse button(forward one page)
+	Bit5 => 5th mouse button(backward one page)
+	Bit6 => scroll left button
+	Bit7 => scroll right button
+
+  When one of the two fingers is up, the device will output four consecutive
+MFMC#0 report packets with zero X and Y to represent 1st finger is up or
+four consecutive MFMC#1 report packets with zero X and Y to represent that
+the 2nd finger is up.  On the other hand, if both fingers are up, the device
+will output four consecutive single-finger, absolute coordinate(SFAC) packets
+with zero X and Y.
+
+Notify Packet for STL3888-Cx/Dx
+   Bit 7 6 5 4 3 2 1 0       7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0      7 6 5 4 3 2 1 0
+BYTE  |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
+  1   |1|0|0|P|1|M|R|L|  2  |C|C|C|C|C|C|C|C|  3 |0|0|F|F|0|0|0|i|  4 |r|l|u|d|0|0|0|0|
+      |---------------|     |---------------|    |---------------|    |---------------|
+
+Byte 1: Bit7~Bit6 => 00, Normal data packet
+                  => 01, Absolute coordinates packet
+                  => 10, Notify packet
+	Bit5 => Always 0
+	Bit4 => 0: The LEFT button is generated by on-pad command(OPC)
+		1: The LEFT button is generated by external button
+		Default is 1 even if the LEFT button is not pressed.
+	Bit3 => 1
+	Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
+	Bit1 => Right Button, 1 is pressed, 0 is not pressed.
+	Bit0 => Left Button, 1 is pressed, 0 is not pressed.
+Byte 2: Message type:
+	0xba => gesture information
+	0xc0 => one finger hold-rotating gesture
+Byte 3: The first parameter for the received message:
+	0xba => gesture ID (refer to the 'Gesture ID' section)
+	0xc0 => region ID
+Byte 4: The second parameter for the received message:
+	0xba => N/A
+	0xc0 => finger up/down information
+
+Sample sequence of Multi-finger, Multi-coordinates mode:
+
+	notify packet (valid bit == 1), MFMC packet 1 (byte 1, bit 2 == 0),
+	MFMC packet 2 (byte 1, bit 2 == 1), MFMC packet 1, MFMC packet 2,
+	..., notify packet (valid bit == 0)
+
+	That is, when the device is in MFMC mode, the host will receive
+	interleaved absolute coordinate packets for each finger.
+
 ==============================================================================
 ==============================================================================
 * FSP Enable/Disable packet
 * FSP Enable/Disable packet
 ==============================================================================
 ==============================================================================
@@ -348,9 +458,10 @@ http://www.computer-engineering.org/ps2mouse/
 ==============================================================================
 ==============================================================================
 1. Identify FSP by reading device ID(0x00) and version(0x01) register
 1. Identify FSP by reading device ID(0x00) and version(0x01) register
 
 
-2. Determine number of buttons by reading status2 (0x0b) register
+2a. For FSP version < STL3888 Cx, determine number of buttons by reading
+    the 'test mode status' (0x20) register:
 
 
-	buttons = reg[0x0b] & 0x30
+	buttons = reg[0x20] & 0x30
 
 
 	if buttons == 0x30 or buttons == 0x20:
 	if buttons == 0x30 or buttons == 0x20:
 		# two/four buttons
 		# two/four buttons
@@ -365,6 +476,10 @@ http://www.computer-engineering.org/ps2mouse/
 		Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
 		Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
 		section A for packet parsing detail
 		section A for packet parsing detail
 
 
+2b. For FSP version >= STL3888 Cx:
+	Refer to 'Finger Sensing Pad PS/2 Mouse Intellimouse'
+	section A for packet parsing detail (ignore byte 4, bit ~ 7)
+
 ==============================================================================
 ==============================================================================
 * Programming Sequence for Register Reading/Writing
 * Programming Sequence for Register Reading/Writing
 ==============================================================================
 ==============================================================================
@@ -374,7 +489,7 @@ Register inversion requirement:
   Following values needed to be inverted(the '~' operator in C) before being
   Following values needed to be inverted(the '~' operator in C) before being
 sent to FSP:
 sent to FSP:
 
 
-	0xe9, 0xee, 0xf2 and 0xff.
+	0xe8, 0xe9, 0xee, 0xf2, 0xf3 and 0xff.
 
 
 Register swapping requirement:
 Register swapping requirement:
 
 
@@ -415,7 +530,18 @@ Register reading sequence:
 
 
 	8. send 0xe9(status request) PS/2 command to FSP;
 	8. send 0xe9(status request) PS/2 command to FSP;
 
 
-	9. the response read from FSP should be the requested register value.
+	9. the 4th byte of the response read from FSP should be the
+	requested register value(?? indicates don't care byte):
+
+		host: 0xe9
+		3888: 0xfa (??) (??) (val)
+
+	* Note that since the Cx release, the hardware will return 1's
+	complement of the register value at the 3rd byte of status request
+	result:
+
+		host: 0xe9
+		3888: 0xfa (??) (~val) (val)
 
 
 Register writing sequence:
 Register writing sequence:
 
 
@@ -465,71 +591,194 @@ Register writing sequence:
 
 
 	9. the register writing sequence is completed.
 	9. the register writing sequence is completed.
 
 
+	* Note that since the Cx release, the hardware will return 1's
+	complement of the register value at the 3rd byte of status request
+	result. Host can optionally send another 0xe9 (status request) PS/2
+	command to FSP at the end of register writing to verify that the
+	register writing operation is successful (?? indicates don't care
+	byte):
+
+		host: 0xe9
+		3888: 0xfa (??) (~val) (val)
+
+==============================================================================
+* Programming Sequence for Page Register Reading/Writing
+==============================================================================
+
+  In order to overcome the limitation of maximum number of registers
+supported, the hardware separates register into different groups called
+'pages.' Each page is able to include up to 255 registers.
+
+  The default page after power up is 0x82; therefore, if one has to get
+access to register 0x8301, one has to use following sequence to switch
+to page 0x83, then start reading/writing from/to offset 0x01 by using
+the register read/write sequence described in previous section.
+
+Page register reading sequence:
+
+	1. send 0xf3 PS/2 command to FSP;
+
+	2. send 0x66 PS/2 command to FSP;
+
+	3. send 0x88 PS/2 command to FSP;
+
+	4. send 0xf3 PS/2 command to FSP;
+
+	5. send 0x83 PS/2 command to FSP;
+
+	6. send 0x88 PS/2 command to FSP;
+
+	7. send 0xe9(status request) PS/2 command to FSP;
+
+	8. the response read from FSP should be the requested page value.
+
+Page register writing sequence:
+
+	1. send 0xf3 PS/2 command to FSP;
+
+	2. send 0x38 PS/2 command to FSP;
+
+	3. send 0x88 PS/2 command to FSP;
+
+	4. send 0xf3 PS/2 command to FSP;
+
+	5. if the page address being written is not required to be
+	inverted(refer to the 'Register inversion requirement' section),
+	goto step 6
+
+	5a. send 0x47 PS/2 command to FSP;
+
+	5b. send the inverted page address to FSP and goto step 9;
+
+	6. if the page address being written is not required to be
+	swapped(refer to the 'Register swapping requirement' section),
+	goto step 7
+
+	6a. send 0x44 PS/2 command to FSP;
+
+	6b. send the swapped page address to FSP and goto step 9;
+
+	7. send 0x33 PS/2 command to FSP;
+
+	8. send the page address to FSP;
+
+	9. the page register writing sequence is completed.
+
+==============================================================================
+* Gesture ID
+==============================================================================
+
+  Unlike other devices which sends multiple fingers' coordinates to host,
+FSP processes multiple fingers' coordinates internally and convert them
+into a 8 bits integer, namely 'Gesture ID.'  Following is a list of
+supported gesture IDs:
+
+	ID	Description
+	0x86	2 finger straight up
+	0x82	2 finger straight down
+	0x80	2 finger straight right
+	0x84	2 finger straight left
+	0x8f	2 finger zoom in
+	0x8b	2 finger zoom out
+	0xc0	2 finger curve, counter clockwise
+	0xc4	2 finger curve, clockwise
+	0x2e	3 finger straight up
+	0x2a	3 finger straight down
+	0x28	3 finger straight right
+	0x2c	3 finger straight left
+	0x38	palm
+
 ==============================================================================
 ==============================================================================
 * Register Listing
 * Register Listing
 ==============================================================================
 ==============================================================================
 
 
+  Registers are represented in 16 bits values. The higher 8 bits represent
+the page address and the lower 8 bits represent the relative offset within
+that particular page.  Refer to the 'Programming Sequence for Page Register
+Reading/Writing' section for instructions on how to change current page
+address.
+
 offset	width		default	r/w	name
 offset	width		default	r/w	name
-0x00	bit7~bit0	0x01	RO	device ID
+0x8200	bit7~bit0	0x01	RO	device ID
 
 
-0x01	bit7~bit0	0xc0	RW	version ID
+0x8201	bit7~bit0		RW	version ID
+					0xc1: STL3888 Ax
+					0xd0 ~ 0xd2: STL3888 Bx
+					0xe0 ~ 0xe1: STL3888 Cx
+					0xe2 ~ 0xe3: STL3888 Dx
 
 
-0x02	bit7~bit0	0x01	RO	vendor ID
+0x8202	bit7~bit0	0x01	RO	vendor ID
 
 
-0x03	bit7~bit0	0x01	RO	product ID
+0x8203	bit7~bit0	0x01	RO	product ID
 
 
-0x04	bit3~bit0	0x01	RW	revision ID
+0x8204	bit3~bit0	0x01	RW	revision ID
 
 
-0x0b				RO	test mode status 1
-	bit3		1	RO	0: rotate 180 degree, 1: no rotation
+0x820b					test mode status 1
+	bit3		1	RO	0: rotate 180 degree
+					1: no rotation
+					*only supported by H/W prior to Cx
 
 
-	bit5~bit4		RO	number of buttons
-			11 => 2, lbtn/rbtn
-			10 => 4, lbtn/rbtn/scru/scrd
-			01 => 6, lbtn/rbtn/scru/scrd/scrl/scrr
-			00 => 6, lbtn/rbtn/scru/scrd/fbtn/bbtn
+0x820f					register file page control
+	bit2		0	RW	1: rotate 180 degree
+					0: no rotation
+					*supported since Cx
 
 
-0x0f				RW	register file page control
 	bit0		0	RW	1 to enable page 1 register files
 	bit0		0	RW	1 to enable page 1 register files
+					*only supported by H/W prior to Cx
 
 
-0x10				RW	system control 1
+0x8210				RW	system control 1
 	bit0		1	RW	Reserved, must be 1
 	bit0		1	RW	Reserved, must be 1
 	bit1		0	RW	Reserved, must be 0
 	bit1		0	RW	Reserved, must be 0
-	bit4		1	RW	Reserved, must be 0
-	bit5		0	RW	register clock gating enable
+	bit4		0	RW	Reserved, must be 0
+	bit5		1	RW	register clock gating enable
 					0: read only, 1: read/write enable
 					0: read only, 1: read/write enable
 	(Note that following registers does not require clock gating being
 	(Note that following registers does not require clock gating being
 	enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
 	enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
 	40 41 42 43.  In addition to that, this bit must be 1 when gesture
 	40 41 42 43.  In addition to that, this bit must be 1 when gesture
 	mode is enabled)
 	mode is enabled)
 
 
-0x31				RW	on-pad command detection
+0x8220					test mode status
+	bit5~bit4		RO	number of buttons
+					11 => 2, lbtn/rbtn
+					10 => 4, lbtn/rbtn/scru/scrd
+					01 => 6, lbtn/rbtn/scru/scrd/scrl/scrr
+					00 => 6, lbtn/rbtn/scru/scrd/fbtn/bbtn
+					*only supported by H/W prior to Cx
+
+0x8231				RW	on-pad command detection
 	bit7		0	RW	on-pad command left button down tag
 	bit7		0	RW	on-pad command left button down tag
 					enable
 					enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
-0x34				RW	on-pad command control 5
+0x8234				RW	on-pad command control 5
 	bit4~bit0	0x05	RW	XLO in 0s/4/1, so 03h = 0010.1b = 2.5
 	bit4~bit0	0x05	RW	XLO in 0s/4/1, so 03h = 0010.1b = 2.5
 	(Note that position unit is in 0.5 scanline)
 	(Note that position unit is in 0.5 scanline)
+					*only supported by H/W prior to Cx
 
 
 	bit7		0	RW	on-pad tap zone enable
 	bit7		0	RW	on-pad tap zone enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
-0x35				RW	on-pad command control 6
+0x8235				RW	on-pad command control 6
 	bit4~bit0	0x1d	RW	XHI in 0s/4/1, so 19h = 1100.1b = 12.5
 	bit4~bit0	0x1d	RW	XHI in 0s/4/1, so 19h = 1100.1b = 12.5
 	(Note that position unit is in 0.5 scanline)
 	(Note that position unit is in 0.5 scanline)
+					*only supported by H/W prior to Cx
 
 
-0x36				RW	on-pad command control 7
+0x8236				RW	on-pad command control 7
 	bit4~bit0	0x04	RW	YLO in 0s/4/1, so 03h = 0010.1b = 2.5
 	bit4~bit0	0x04	RW	YLO in 0s/4/1, so 03h = 0010.1b = 2.5
 	(Note that position unit is in 0.5 scanline)
 	(Note that position unit is in 0.5 scanline)
+					*only supported by H/W prior to Cx
 
 
-0x37				RW	on-pad command control 8
+0x8237				RW	on-pad command control 8
 	bit4~bit0	0x13	RW	YHI in 0s/4/1, so 11h = 1000.1b = 8.5
 	bit4~bit0	0x13	RW	YHI in 0s/4/1, so 11h = 1000.1b = 8.5
 	(Note that position unit is in 0.5 scanline)
 	(Note that position unit is in 0.5 scanline)
+					*only supported by H/W prior to Cx
 
 
-0x40				RW	system control 5
+0x8240				RW	system control 5
 	bit1		0	RW	FSP Intellimouse mode enable
 	bit1		0	RW	FSP Intellimouse mode enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
 	bit2		0	RW	movement + abs. coordinate mode enable
 	bit2		0	RW	movement + abs. coordinate mode enable
 					0: disable, 1: enable
 					0: disable, 1: enable
@@ -537,6 +786,7 @@ offset	width		default	r/w	name
 	bit 1 is not set. However, the format is different from that of bit 1.
 	bit 1 is not set. However, the format is different from that of bit 1.
 	In addition, when bit 1 and bit 2 are set at the same time, bit 2 will
 	In addition, when bit 1 and bit 2 are set at the same time, bit 2 will
 	override bit 1.)
 	override bit 1.)
+					*only supported by H/W prior to Cx
 
 
 	bit3		0	RW	abs. coordinate only mode enable
 	bit3		0	RW	abs. coordinate only mode enable
 					0: disable, 1: enable
 					0: disable, 1: enable
@@ -544,9 +794,11 @@ offset	width		default	r/w	name
 	bit 1 is not set. However, the format is different from that of bit 1.
 	bit 1 is not set. However, the format is different from that of bit 1.
 	In addition, when bit 1, bit 2 and bit 3 are set at the same time,
 	In addition, when bit 1, bit 2 and bit 3 are set at the same time,
 	bit 3 will override bit 1 and 2.)
 	bit 3 will override bit 1 and 2.)
+					*only supported by H/W prior to Cx
 
 
 	bit5		0	RW	auto switch enable
 	bit5		0	RW	auto switch enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
 	bit6		0	RW	G0 abs. + notify packet format enable
 	bit6		0	RW	G0 abs. + notify packet format enable
 					0: disable, 1: enable
 					0: disable, 1: enable
@@ -554,18 +806,68 @@ offset	width		default	r/w	name
 	bit 2 and 3.  That is, if any of those bit is 1, host will receive
 	bit 2 and 3.  That is, if any of those bit is 1, host will receive
 	absolute coordinates; otherwise, host only receives packets with
 	absolute coordinates; otherwise, host only receives packets with
 	relative coordinate.)
 	relative coordinate.)
+					*only supported by H/W prior to Cx
 
 
 	bit7		0	RW	EN_PS2_F2: PS/2 gesture mode 2nd
 	bit7		0	RW	EN_PS2_F2: PS/2 gesture mode 2nd
 					finger packet enable
 					finger packet enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
-0x43				RW	on-pad control
+0x8243				RW	on-pad control
 	bit0		0	RW	on-pad control enable
 	bit0		0	RW	on-pad control enable
 					0: disable, 1: enable
 					0: disable, 1: enable
 	(Note that if this bit is cleared, bit 3/5 will be ineffective)
 	(Note that if this bit is cleared, bit 3/5 will be ineffective)
+					*only supported by H/W prior to Cx
 
 
 	bit3		0	RW	on-pad fix vertical scrolling enable
 	bit3		0	RW	on-pad fix vertical scrolling enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
 
 
 	bit5		0	RW	on-pad fix horizontal scrolling enable
 	bit5		0	RW	on-pad fix horizontal scrolling enable
 					0: disable, 1: enable
 					0: disable, 1: enable
+					*only supported by H/W prior to Cx
+
+0x8290				RW	software control register 1
+	bit0		0	RW	absolute coordination mode
+					0: disable, 1: enable
+					*supported since Cx
+
+	bit1		0	RW	gesture ID output
+					0: disable, 1: enable
+					*supported since Cx
+
+	bit2		0	RW	two fingers' coordinates output
+					0: disable, 1: enable
+					*supported since Cx
+
+	bit3		0	RW	finger up one packet output
+					0: disable, 1: enable
+					*supported since Cx
+
+	bit4		0	RW	absolute coordination continuous mode
+					0: disable, 1: enable
+					*supported since Cx
+
+	bit6~bit5	00	RW	gesture group selection
+					00: basic
+					01: suite
+					10: suite pro
+					11: advanced
+					*supported since Cx
+
+	bit7		0	RW	Bx packet output compatible mode
+					0: disable, 1: enable					*supported since Cx
+					*supported since Cx
+
+
+0x833d				RW	on-pad command control 1
+	bit7		1	RW	on-pad command detection enable
+					0: disable, 1: enable
+					*supported since Cx
+
+0x833e				RW	on-pad command detection
+	bit7		0	RW	on-pad command left button down tag
+					enable. Works only in H/W based PS/2
+					data packet mode.
+					0: disable, 1: enable
+					*supported since Cx

+ 1 - 0
arch/arm/mach-tegra/include/mach/kbc.h

@@ -53,6 +53,7 @@ struct tegra_kbc_platform_data {
 	struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO];
 	struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO];
 	const struct matrix_keymap_data *keymap_data;
 	const struct matrix_keymap_data *keymap_data;
 
 
+	u32 wakeup_key;
 	bool wakeup;
 	bool wakeup;
 	bool use_fn_map;
 	bool use_fn_map;
 	bool use_ghost_filter;
 	bool use_ghost_filter;

+ 1 - 26
arch/arm/plat-samsung/include/plat/keypad.h

@@ -13,32 +13,7 @@
 #ifndef __PLAT_SAMSUNG_KEYPAD_H
 #ifndef __PLAT_SAMSUNG_KEYPAD_H
 #define __PLAT_SAMSUNG_KEYPAD_H
 #define __PLAT_SAMSUNG_KEYPAD_H
 
 
-#include <linux/input/matrix_keypad.h>
-
-#define SAMSUNG_MAX_ROWS	8
-#define SAMSUNG_MAX_COLS	8
-
-/**
- * struct samsung_keypad_platdata - Platform device data for Samsung Keypad.
- * @keymap_data: pointer to &matrix_keymap_data.
- * @rows: number of keypad row supported.
- * @cols: number of keypad col supported.
- * @no_autorepeat: disable key autorepeat.
- * @wakeup: controls whether the device should be set up as wakeup source.
- * @cfg_gpio: configure the GPIO.
- *
- * Initialisation data specific to either the machine or the platform
- * for the device driver to use or call-back when configuring gpio.
- */
-struct samsung_keypad_platdata {
-	const struct matrix_keymap_data	*keymap_data;
-	unsigned int rows;
-	unsigned int cols;
-	bool no_autorepeat;
-	bool wakeup;
-
-	void (*cfg_gpio)(unsigned int rows, unsigned int cols);
-};
+#include <linux/input/samsung-keypad.h>
 
 
 /**
 /**
  * samsung_keypad_set_platdata - Set platform data for Samsung Keypad device.
  * samsung_keypad_set_platdata - Set platform data for Samsung Keypad device.

+ 11 - 9
drivers/input/evdev.c

@@ -369,7 +369,7 @@ static int evdev_fetch_next_event(struct evdev_client *client,
 
 
 	spin_lock_irq(&client->buffer_lock);
 	spin_lock_irq(&client->buffer_lock);
 
 
-	have_event = client->head != client->tail;
+	have_event = client->packet_head != client->tail;
 	if (have_event) {
 	if (have_event) {
 		*event = client->buffer[client->tail++];
 		*event = client->buffer[client->tail++];
 		client->tail &= client->bufsize - 1;
 		client->tail &= client->bufsize - 1;
@@ -391,14 +391,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
 	if (count < input_event_size())
 	if (count < input_event_size())
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (client->packet_head == client->tail && evdev->exist &&
-	    (file->f_flags & O_NONBLOCK))
-		return -EAGAIN;
-
-	retval = wait_event_interruptible(evdev->wait,
-		client->packet_head != client->tail || !evdev->exist);
-	if (retval)
-		return retval;
+	if (!(file->f_flags & O_NONBLOCK)) {
+		retval = wait_event_interruptible(evdev->wait,
+				client->packet_head != client->tail ||
+				!evdev->exist);
+		if (retval)
+			return retval;
+	}
 
 
 	if (!evdev->exist)
 	if (!evdev->exist)
 		return -ENODEV;
 		return -ENODEV;
@@ -412,6 +411,9 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
 		retval += input_event_size();
 		retval += input_event_size();
 	}
 	}
 
 
+	if (retval == 0 && (file->f_flags & O_NONBLOCK))
+		return -EAGAIN;
+
 	return retval;
 	return retval;
 }
 }
 
 

+ 5 - 3
drivers/input/input-polldev.c

@@ -84,10 +84,12 @@ static ssize_t input_polldev_set_poll(struct device *dev,
 {
 {
 	struct input_polled_dev *polldev = dev_get_drvdata(dev);
 	struct input_polled_dev *polldev = dev_get_drvdata(dev);
 	struct input_dev *input = polldev->input;
 	struct input_dev *input = polldev->input;
-	unsigned long interval;
+	unsigned int interval;
+	int err;
 
 
-	if (strict_strtoul(buf, 0, &interval))
-		return -EINVAL;
+	err = kstrtouint(buf, 0, &interval);
+	if (err)
+		return err;
 
 
 	if (interval < polldev->poll_interval_min)
 	if (interval < polldev->poll_interval_min)
 		return -EINVAL;
 		return -EINVAL;

+ 19 - 2
drivers/input/keyboard/Kconfig

@@ -221,6 +221,22 @@ config KEYBOARD_TCA6416
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called tca6416_keypad.
 	  module will be called tca6416_keypad.
 
 
+config KEYBOARD_TCA8418
+	tristate "TCA8418 Keypad Support"
+	depends on I2C
+	help
+	  This driver implements basic keypad functionality
+	  for keys connected through TCA8418 keypad decoder.
+
+	  Say Y here if your device has keys connected to
+	  TCA8418 keypad decoder.
+
+	  If enabled the complete TCA8418 device will be managed through
+	  this driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tca8418_keypad.
+
 config KEYBOARD_MATRIX
 config KEYBOARD_MATRIX
 	tristate "GPIO driven matrix keypad support"
 	tristate "GPIO driven matrix keypad support"
 	depends on GENERIC_GPIO
 	depends on GENERIC_GPIO
@@ -425,9 +441,10 @@ config KEYBOARD_PMIC8XXX
 
 
 config KEYBOARD_SAMSUNG
 config KEYBOARD_SAMSUNG
 	tristate "Samsung keypad support"
 	tristate "Samsung keypad support"
-	depends on SAMSUNG_DEV_KEYPAD
+	depends on HAVE_CLK
 	help
 	help
-	  Say Y here if you want to use the Samsung keypad.
+	  Say Y here if you want to use the keypad on your Samsung mobile
+	  device.
 
 
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called samsung-keypad.
 	  module will be called samsung-keypad.

+ 1 - 0
drivers/input/keyboard/Makefile

@@ -16,6 +16,7 @@ obj-$(CONFIG_KEYBOARD_EP93XX)		+= ep93xx_keypad.o
 obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 obj-$(CONFIG_KEYBOARD_GPIO)		+= gpio_keys.o
 obj-$(CONFIG_KEYBOARD_GPIO_POLLED)	+= gpio_keys_polled.o
 obj-$(CONFIG_KEYBOARD_GPIO_POLLED)	+= gpio_keys_polled.o
 obj-$(CONFIG_KEYBOARD_TCA6416)		+= tca6416-keypad.o
 obj-$(CONFIG_KEYBOARD_TCA6416)		+= tca6416-keypad.o
+obj-$(CONFIG_KEYBOARD_TCA8418)		+= tca8418_keypad.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
 obj-$(CONFIG_KEYBOARD_IMX)		+= imx_keypad.o
 obj-$(CONFIG_KEYBOARD_IMX)		+= imx_keypad.o

+ 1 - 12
drivers/input/keyboard/adp5520-keys.c

@@ -202,18 +202,7 @@ static struct platform_driver adp5520_keys_driver = {
 	.probe		= adp5520_keys_probe,
 	.probe		= adp5520_keys_probe,
 	.remove		= __devexit_p(adp5520_keys_remove),
 	.remove		= __devexit_p(adp5520_keys_remove),
 };
 };
-
-static int __init adp5520_keys_init(void)
-{
-	return platform_driver_register(&adp5520_keys_driver);
-}
-module_init(adp5520_keys_init);
-
-static void __exit adp5520_keys_exit(void)
-{
-	platform_driver_unregister(&adp5520_keys_driver);
-}
-module_exit(adp5520_keys_exit);
+module_platform_driver(adp5520_keys_driver);
 
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("Keys ADP5520 Driver");
 MODULE_DESCRIPTION("Keys ADP5520 Driver");

+ 1 - 14
drivers/input/keyboard/amikbd.c

@@ -259,19 +259,6 @@ static struct platform_driver amikbd_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init amikbd_init(void)
-{
-	return platform_driver_probe(&amikbd_driver, amikbd_probe);
-}
-
-module_init(amikbd_init);
-
-static void __exit amikbd_exit(void)
-{
-	platform_driver_unregister(&amikbd_driver);
-}
-
-module_exit(amikbd_exit);
+module_platform_driver(amikbd_driver);
 
 
 MODULE_ALIAS("platform:amiga-keyboard");
 MODULE_ALIAS("platform:amiga-keyboard");

+ 30 - 10
drivers/input/keyboard/atkbd.c

@@ -1305,7 +1305,7 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
 static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
 static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
 {
 {
 	struct input_dev *old_dev, *new_dev;
 	struct input_dev *old_dev, *new_dev;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 	bool old_extra;
 	bool old_extra;
 	unsigned char old_set;
 	unsigned char old_set;
@@ -1313,7 +1313,11 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
 	if (!atkbd->write)
 	if (!atkbd->write)
 		return -EIO;
 		return -EIO;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (atkbd->extra != value) {
 	if (atkbd->extra != value) {
@@ -1389,11 +1393,15 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
 static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
 static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
 {
 {
 	struct input_dev *old_dev, *new_dev;
 	struct input_dev *old_dev, *new_dev;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 	bool old_scroll;
 	bool old_scroll;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (atkbd->scroll != value) {
 	if (atkbd->scroll != value) {
@@ -1433,7 +1441,7 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
 static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 {
 {
 	struct input_dev *old_dev, *new_dev;
 	struct input_dev *old_dev, *new_dev;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 	unsigned char old_set;
 	unsigned char old_set;
 	bool old_extra;
 	bool old_extra;
@@ -1441,7 +1449,11 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
 	if (!atkbd->write)
 	if (!atkbd->write)
 		return -EIO;
 		return -EIO;
 
 
-	if (strict_strtoul(buf, 10, &value) || (value != 2 && value != 3))
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value != 2 && value != 3)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (atkbd->set != value) {
 	if (atkbd->set != value) {
@@ -1484,14 +1496,18 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
 static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
 static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
 {
 {
 	struct input_dev *old_dev, *new_dev;
 	struct input_dev *old_dev, *new_dev;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 	bool old_softrepeat, old_softraw;
 	bool old_softrepeat, old_softraw;
 
 
 	if (!atkbd->write)
 	if (!atkbd->write)
 		return -EIO;
 		return -EIO;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (atkbd->softrepeat != value) {
 	if (atkbd->softrepeat != value) {
@@ -1534,11 +1550,15 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
 static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
 static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
 {
 {
 	struct input_dev *old_dev, *new_dev;
 	struct input_dev *old_dev, *new_dev;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 	bool old_softraw;
 	bool old_softraw;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (atkbd->softraw != value) {
 	if (atkbd->softraw != value) {

+ 2 - 14
drivers/input/keyboard/bf54x-keys.c

@@ -384,7 +384,7 @@ static int bfin_kpad_resume(struct platform_device *pdev)
 # define bfin_kpad_resume  NULL
 # define bfin_kpad_resume  NULL
 #endif
 #endif
 
 
-struct platform_driver bfin_kpad_device_driver = {
+static struct platform_driver bfin_kpad_device_driver = {
 	.driver		= {
 	.driver		= {
 		.name	= DRV_NAME,
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
@@ -394,19 +394,7 @@ struct platform_driver bfin_kpad_device_driver = {
 	.suspend	= bfin_kpad_suspend,
 	.suspend	= bfin_kpad_suspend,
 	.resume		= bfin_kpad_resume,
 	.resume		= bfin_kpad_resume,
 };
 };
-
-static int __init bfin_kpad_init(void)
-{
-	return platform_driver_register(&bfin_kpad_device_driver);
-}
-
-static void __exit bfin_kpad_exit(void)
-{
-	platform_driver_unregister(&bfin_kpad_device_driver);
-}
-
-module_init(bfin_kpad_init);
-module_exit(bfin_kpad_exit);
+module_platform_driver(bfin_kpad_device_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");

+ 1 - 12
drivers/input/keyboard/davinci_keyscan.c

@@ -328,18 +328,7 @@ static struct platform_driver davinci_ks_driver = {
 	},
 	},
 	.remove	= __devexit_p(davinci_ks_remove),
 	.remove	= __devexit_p(davinci_ks_remove),
 };
 };
-
-static int __init davinci_ks_init(void)
-{
-	return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe);
-}
-module_init(davinci_ks_init);
-
-static void __exit davinci_ks_exit(void)
-{
-	platform_driver_unregister(&davinci_ks_driver);
-}
-module_exit(davinci_ks_exit);
+module_platform_driver(davinci_ks_driver);
 
 
 MODULE_AUTHOR("Miguel Aguilar");
 MODULE_AUTHOR("Miguel Aguilar");
 MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
 MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");

+ 1 - 13
drivers/input/keyboard/ep93xx_keypad.c

@@ -390,19 +390,7 @@ static struct platform_driver ep93xx_keypad_driver = {
 	.suspend	= ep93xx_keypad_suspend,
 	.suspend	= ep93xx_keypad_suspend,
 	.resume		= ep93xx_keypad_resume,
 	.resume		= ep93xx_keypad_resume,
 };
 };
-
-static int __init ep93xx_keypad_init(void)
-{
-	return platform_driver_register(&ep93xx_keypad_driver);
-}
-
-static void __exit ep93xx_keypad_exit(void)
-{
-	platform_driver_unregister(&ep93xx_keypad_driver);
-}
-
-module_init(ep93xx_keypad_init);
-module_exit(ep93xx_keypad_exit);
+module_platform_driver(ep93xx_keypad_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");

+ 1 - 13
drivers/input/keyboard/gpio_keys_polled.c

@@ -241,19 +241,7 @@ static struct platform_driver gpio_keys_polled_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init gpio_keys_polled_init(void)
-{
-	return platform_driver_register(&gpio_keys_polled_driver);
-}
-
-static void __exit gpio_keys_polled_exit(void)
-{
-	platform_driver_unregister(&gpio_keys_polled_driver);
-}
-
-module_init(gpio_keys_polled_init);
-module_exit(gpio_keys_polled_exit);
+module_platform_driver(gpio_keys_polled_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");

+ 1 - 13
drivers/input/keyboard/imx_keypad.c

@@ -619,19 +619,7 @@ static struct platform_driver imx_keypad_driver = {
 	.probe		= imx_keypad_probe,
 	.probe		= imx_keypad_probe,
 	.remove		= __devexit_p(imx_keypad_remove),
 	.remove		= __devexit_p(imx_keypad_remove),
 };
 };
-
-static int __init imx_keypad_init(void)
-{
-	return platform_driver_register(&imx_keypad_driver);
-}
-
-static void __exit imx_keypad_exit(void)
-{
-	platform_driver_unregister(&imx_keypad_driver);
-}
-
-module_init(imx_keypad_init);
-module_exit(imx_keypad_exit);
+module_platform_driver(imx_keypad_driver);
 
 
 MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 MODULE_DESCRIPTION("IMX Keypad Port Driver");
 MODULE_DESCRIPTION("IMX Keypad Port Driver");

+ 1 - 13
drivers/input/keyboard/jornada680_kbd.c

@@ -260,19 +260,7 @@ static struct platform_driver jornada680kbd_driver = {
 	.probe	= jornada680kbd_probe,
 	.probe	= jornada680kbd_probe,
 	.remove	= __devexit_p(jornada680kbd_remove),
 	.remove	= __devexit_p(jornada680kbd_remove),
 };
 };
-
-static int __init jornada680kbd_init(void)
-{
-	return platform_driver_register(&jornada680kbd_driver);
-}
-
-static void __exit jornada680kbd_exit(void)
-{
-	platform_driver_unregister(&jornada680kbd_driver);
-}
-
-module_init(jornada680kbd_init);
-module_exit(jornada680kbd_exit);
+module_platform_driver(jornada680kbd_driver);
 
 
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
 MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");

+ 1 - 13
drivers/input/keyboard/jornada720_kbd.c

@@ -174,16 +174,4 @@ static struct platform_driver jornada720_kbd_driver = {
 	.probe   = jornada720_kbd_probe,
 	.probe   = jornada720_kbd_probe,
 	.remove  = __devexit_p(jornada720_kbd_remove),
 	.remove  = __devexit_p(jornada720_kbd_remove),
 };
 };
-
-static int __init jornada720_kbd_init(void)
-{
-	return platform_driver_register(&jornada720_kbd_driver);
-}
-
-static void __exit jornada720_kbd_exit(void)
-{
-	platform_driver_unregister(&jornada720_kbd_driver);
-}
-
-module_init(jornada720_kbd_init);
-module_exit(jornada720_kbd_exit);
+module_platform_driver(jornada720_kbd_driver);

+ 5 - 6
drivers/input/keyboard/lm8323.c

@@ -545,13 +545,12 @@ static ssize_t lm8323_pwm_store_time(struct device *dev,
 {
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
 	struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
 	struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev);
-	int ret;
-	unsigned long time;
+	int ret, time;
 
 
-	ret = strict_strtoul(buf, 10, &time);
+	ret = kstrtoint(buf, 10, &time);
 	/* Numbers only, please. */
 	/* Numbers only, please. */
 	if (ret)
 	if (ret)
-		return -EINVAL;
+		return ret;
 
 
 	pwm->fade_time = time;
 	pwm->fade_time = time;
 
 
@@ -613,9 +612,9 @@ static ssize_t lm8323_set_disable(struct device *dev,
 {
 {
 	struct lm8323_chip *lm = dev_get_drvdata(dev);
 	struct lm8323_chip *lm = dev_get_drvdata(dev);
 	int ret;
 	int ret;
-	unsigned long i;
+	unsigned int i;
 
 
-	ret = strict_strtoul(buf, 10, &i);
+	ret = kstrtouint(buf, 10, &i);
 
 
 	mutex_lock(&lm->lock);
 	mutex_lock(&lm->lock);
 	lm->kp_enabled = !i;
 	lm->kp_enabled = !i;

+ 1 - 13
drivers/input/keyboard/matrix_keypad.c

@@ -496,19 +496,7 @@ static struct platform_driver matrix_keypad_driver = {
 #endif
 #endif
 	},
 	},
 };
 };
-
-static int __init matrix_keypad_init(void)
-{
-	return platform_driver_register(&matrix_keypad_driver);
-}
-
-static void __exit matrix_keypad_exit(void)
-{
-	platform_driver_unregister(&matrix_keypad_driver);
-}
-
-module_init(matrix_keypad_init);
-module_exit(matrix_keypad_exit);
+module_platform_driver(matrix_keypad_driver);
 
 
 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
 MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");

+ 2 - 13
drivers/input/keyboard/nomadik-ske-keypad.c

@@ -379,7 +379,7 @@ static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
 };
 };
 #endif
 #endif
 
 
-struct platform_driver ske_keypad_driver = {
+static struct platform_driver ske_keypad_driver = {
 	.driver = {
 	.driver = {
 		.name = "nmk-ske-keypad",
 		.name = "nmk-ske-keypad",
 		.owner  = THIS_MODULE,
 		.owner  = THIS_MODULE,
@@ -390,18 +390,7 @@ struct platform_driver ske_keypad_driver = {
 	.probe = ske_keypad_probe,
 	.probe = ske_keypad_probe,
 	.remove = __devexit_p(ske_keypad_remove),
 	.remove = __devexit_p(ske_keypad_remove),
 };
 };
-
-static int __init ske_keypad_init(void)
-{
-	return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
-}
-module_init(ske_keypad_init);
-
-static void __exit ske_keypad_exit(void)
-{
-	platform_driver_unregister(&ske_keypad_driver);
-}
-module_exit(ske_keypad_exit);
+module_platform_driver(ske_keypad_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
 MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");

+ 1 - 14
drivers/input/keyboard/omap-keypad.c

@@ -473,20 +473,7 @@ static struct platform_driver omap_kp_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init omap_kp_init(void)
-{
-	printk(KERN_INFO "OMAP Keypad Driver\n");
-	return platform_driver_register(&omap_kp_driver);
-}
-
-static void __exit omap_kp_exit(void)
-{
-	platform_driver_unregister(&omap_kp_driver);
-}
-
-module_init(omap_kp_init);
-module_exit(omap_kp_exit);
+module_platform_driver(omap_kp_driver);
 
 
 MODULE_AUTHOR("Timo Teräs");
 MODULE_AUTHOR("Timo Teräs");
 MODULE_DESCRIPTION("OMAP Keypad Driver");
 MODULE_DESCRIPTION("OMAP Keypad Driver");

+ 1 - 12
drivers/input/keyboard/omap4-keypad.c

@@ -335,18 +335,7 @@ static struct platform_driver omap4_keypad_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init omap4_keypad_init(void)
-{
-	return platform_driver_register(&omap4_keypad_driver);
-}
-module_init(omap4_keypad_init);
-
-static void __exit omap4_keypad_exit(void)
-{
-	platform_driver_unregister(&omap4_keypad_driver);
-}
-module_exit(omap4_keypad_exit);
+module_platform_driver(omap4_keypad_driver);
 
 
 MODULE_AUTHOR("Texas Instruments");
 MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("OMAP4 Keypad Driver");
 MODULE_DESCRIPTION("OMAP4 Keypad Driver");

+ 1 - 12
drivers/input/keyboard/opencores-kbd.c

@@ -163,18 +163,7 @@ static struct platform_driver opencores_kbd_device_driver = {
 		.name = "opencores-kbd",
 		.name = "opencores-kbd",
 	},
 	},
 };
 };
-
-static int __init opencores_kbd_init(void)
-{
-	return platform_driver_register(&opencores_kbd_device_driver);
-}
-module_init(opencores_kbd_init);
-
-static void __exit opencores_kbd_exit(void)
-{
-	platform_driver_unregister(&opencores_kbd_device_driver);
-}
-module_exit(opencores_kbd_exit);
+module_platform_driver(opencores_kbd_device_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>");
 MODULE_AUTHOR("Javier Herrero <jherrero@hvsistemas.es>");

+ 1 - 12
drivers/input/keyboard/pmic8xxx-keypad.c

@@ -780,18 +780,7 @@ static struct platform_driver pmic8xxx_kp_driver = {
 		.pm = &pm8xxx_kp_pm_ops,
 		.pm = &pm8xxx_kp_pm_ops,
 	},
 	},
 };
 };
-
-static int __init pmic8xxx_kp_init(void)
-{
-	return platform_driver_register(&pmic8xxx_kp_driver);
-}
-module_init(pmic8xxx_kp_init);
-
-static void __exit pmic8xxx_kp_exit(void)
-{
-	platform_driver_unregister(&pmic8xxx_kp_driver);
-}
-module_exit(pmic8xxx_kp_exit);
+module_platform_driver(pmic8xxx_kp_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("PMIC8XXX keypad driver");
 MODULE_DESCRIPTION("PMIC8XXX keypad driver");

+ 1 - 13
drivers/input/keyboard/pxa27x_keypad.c

@@ -602,19 +602,7 @@ static struct platform_driver pxa27x_keypad_driver = {
 #endif
 #endif
 	},
 	},
 };
 };
-
-static int __init pxa27x_keypad_init(void)
-{
-	return platform_driver_register(&pxa27x_keypad_driver);
-}
-
-static void __exit pxa27x_keypad_exit(void)
-{
-	platform_driver_unregister(&pxa27x_keypad_driver);
-}
-
-module_init(pxa27x_keypad_init);
-module_exit(pxa27x_keypad_exit);
+module_platform_driver(pxa27x_keypad_driver);
 
 
 MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
 MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 1 - 12
drivers/input/keyboard/pxa930_rotary.c

@@ -195,18 +195,7 @@ static struct platform_driver pxa930_rotary_driver = {
 	.probe		= pxa930_rotary_probe,
 	.probe		= pxa930_rotary_probe,
 	.remove		= __devexit_p(pxa930_rotary_remove),
 	.remove		= __devexit_p(pxa930_rotary_remove),
 };
 };
-
-static int __init pxa930_rotary_init(void)
-{
-	return platform_driver_register(&pxa930_rotary_driver);
-}
-module_init(pxa930_rotary_init);
-
-static void __exit pxa930_rotary_exit(void)
-{
-	platform_driver_unregister(&pxa930_rotary_driver);
-}
-module_exit(pxa930_rotary_exit);
+module_platform_driver(pxa930_rotary_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
 MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");

+ 82 - 26
drivers/input/keyboard/samsung-keypad.c

@@ -20,11 +20,13 @@
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
-#include <plat/keypad.h>
+#include <linux/input/samsung-keypad.h>
 
 
 #define SAMSUNG_KEYIFCON			0x00
 #define SAMSUNG_KEYIFCON			0x00
 #define SAMSUNG_KEYIFSTSCLR			0x04
 #define SAMSUNG_KEYIFSTSCLR			0x04
@@ -65,10 +67,12 @@ enum samsung_keypad_type {
 
 
 struct samsung_keypad {
 struct samsung_keypad {
 	struct input_dev *input_dev;
 	struct input_dev *input_dev;
+	struct platform_device *pdev;
 	struct clk *clk;
 	struct clk *clk;
 	void __iomem *base;
 	void __iomem *base;
 	wait_queue_head_t wait;
 	wait_queue_head_t wait;
 	bool stopped;
 	bool stopped;
+	bool wake_enabled;
 	int irq;
 	int irq;
 	enum samsung_keypad_type type;
 	enum samsung_keypad_type type;
 	unsigned int row_shift;
 	unsigned int row_shift;
@@ -155,6 +159,8 @@ static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
 	unsigned int val;
 	unsigned int val;
 	bool key_down;
 	bool key_down;
 
 
+	pm_runtime_get_sync(&keypad->pdev->dev);
+
 	do {
 	do {
 		val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
 		val = readl(keypad->base + SAMSUNG_KEYIFSTSCLR);
 		/* Clear interrupt. */
 		/* Clear interrupt. */
@@ -169,6 +175,8 @@ static irqreturn_t samsung_keypad_irq(int irq, void *dev_id)
 
 
 	} while (key_down && !keypad->stopped);
 	} while (key_down && !keypad->stopped);
 
 
+	pm_runtime_put_sync(&keypad->pdev->dev);
+
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -176,6 +184,8 @@ static void samsung_keypad_start(struct samsung_keypad *keypad)
 {
 {
 	unsigned int val;
 	unsigned int val;
 
 
+	pm_runtime_get_sync(&keypad->pdev->dev);
+
 	/* Tell IRQ thread that it may poll the device. */
 	/* Tell IRQ thread that it may poll the device. */
 	keypad->stopped = false;
 	keypad->stopped = false;
 
 
@@ -188,12 +198,16 @@ static void samsung_keypad_start(struct samsung_keypad *keypad)
 
 
 	/* KEYIFCOL reg clear. */
 	/* KEYIFCOL reg clear. */
 	writel(0, keypad->base + SAMSUNG_KEYIFCOL);
 	writel(0, keypad->base + SAMSUNG_KEYIFCOL);
+
+	pm_runtime_put_sync(&keypad->pdev->dev);
 }
 }
 
 
 static void samsung_keypad_stop(struct samsung_keypad *keypad)
 static void samsung_keypad_stop(struct samsung_keypad *keypad)
 {
 {
 	unsigned int val;
 	unsigned int val;
 
 
+	pm_runtime_get_sync(&keypad->pdev->dev);
+
 	/* Signal IRQ thread to stop polling and disable the handler. */
 	/* Signal IRQ thread to stop polling and disable the handler. */
 	keypad->stopped = true;
 	keypad->stopped = true;
 	wake_up(&keypad->wait);
 	wake_up(&keypad->wait);
@@ -214,6 +228,8 @@ static void samsung_keypad_stop(struct samsung_keypad *keypad)
 	 * re-enable the handler.
 	 * re-enable the handler.
 	 */
 	 */
 	enable_irq(keypad->irq);
 	enable_irq(keypad->irq);
+
+	pm_runtime_put_sync(&keypad->pdev->dev);
 }
 }
 
 
 static int samsung_keypad_open(struct input_dev *input_dev)
 static int samsung_keypad_open(struct input_dev *input_dev)
@@ -418,9 +434,11 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	keypad->input_dev = input_dev;
 	keypad->input_dev = input_dev;
+	keypad->pdev = pdev;
 	keypad->row_shift = row_shift;
 	keypad->row_shift = row_shift;
 	keypad->rows = pdata->rows;
 	keypad->rows = pdata->rows;
 	keypad->cols = pdata->cols;
 	keypad->cols = pdata->cols;
+	keypad->stopped = true;
 	init_waitqueue_head(&keypad->wait);
 	init_waitqueue_head(&keypad->wait);
 
 
 	if (pdev->dev.of_node) {
 	if (pdev->dev.of_node) {
@@ -467,13 +485,14 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 		goto err_put_clk;
 		goto err_put_clk;
 	}
 	}
 
 
+	device_init_wakeup(&pdev->dev, pdata->wakeup);
+	platform_set_drvdata(pdev, keypad);
+	pm_runtime_enable(&pdev->dev);
+
 	error = input_register_device(keypad->input_dev);
 	error = input_register_device(keypad->input_dev);
 	if (error)
 	if (error)
 		goto err_free_irq;
 		goto err_free_irq;
 
 
-	device_init_wakeup(&pdev->dev, pdata->wakeup);
-	platform_set_drvdata(pdev, keypad);
-
 	if (pdev->dev.of_node) {
 	if (pdev->dev.of_node) {
 		devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
 		devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
 		devm_kfree(&pdev->dev, (void *)pdata->keymap_data);
 		devm_kfree(&pdev->dev, (void *)pdata->keymap_data);
@@ -483,6 +502,9 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
 
 
 err_free_irq:
 err_free_irq:
 	free_irq(keypad->irq, keypad);
 	free_irq(keypad->irq, keypad);
+	pm_runtime_disable(&pdev->dev);
+	device_init_wakeup(&pdev->dev, 0);
+	platform_set_drvdata(pdev, NULL);
 err_put_clk:
 err_put_clk:
 	clk_put(keypad->clk);
 	clk_put(keypad->clk);
 	samsung_keypad_dt_gpio_free(keypad);
 	samsung_keypad_dt_gpio_free(keypad);
@@ -499,6 +521,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
 {
 {
 	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
 	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
 
 
+	pm_runtime_disable(&pdev->dev);
 	device_init_wakeup(&pdev->dev, 0);
 	device_init_wakeup(&pdev->dev, 0);
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 
 
@@ -519,11 +542,57 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int samsung_keypad_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
+	unsigned int val;
+	int error;
+
+	if (keypad->stopped)
+		return 0;
+
+	/* This may fail on some SoCs due to lack of controller support */
+	error = enable_irq_wake(keypad->irq);
+	if (!error)
+		keypad->wake_enabled = true;
+
+	val = readl(keypad->base + SAMSUNG_KEYIFCON);
+	val |= SAMSUNG_KEYIFCON_WAKEUPEN;
+	writel(val, keypad->base + SAMSUNG_KEYIFCON);
+
+	clk_disable(keypad->clk);
+
+	return 0;
+}
+
+static int samsung_keypad_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct samsung_keypad *keypad = platform_get_drvdata(pdev);
+	unsigned int val;
+
+	if (keypad->stopped)
+		return 0;
+
+	clk_enable(keypad->clk);
+
+	val = readl(keypad->base + SAMSUNG_KEYIFCON);
+	val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
+	writel(val, keypad->base + SAMSUNG_KEYIFCON);
+
+	if (keypad->wake_enabled)
+		disable_irq_wake(keypad->irq);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
 static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad,
 static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad,
 					 bool enable)
 					 bool enable)
 {
 {
-	struct device *dev = keypad->input_dev->dev.parent;
 	unsigned int val;
 	unsigned int val;
 
 
 	clk_enable(keypad->clk);
 	clk_enable(keypad->clk);
@@ -531,11 +600,11 @@ static void samsung_keypad_toggle_wakeup(struct samsung_keypad *keypad,
 	val = readl(keypad->base + SAMSUNG_KEYIFCON);
 	val = readl(keypad->base + SAMSUNG_KEYIFCON);
 	if (enable) {
 	if (enable) {
 		val |= SAMSUNG_KEYIFCON_WAKEUPEN;
 		val |= SAMSUNG_KEYIFCON_WAKEUPEN;
-		if (device_may_wakeup(dev))
+		if (device_may_wakeup(&keypad->pdev->dev))
 			enable_irq_wake(keypad->irq);
 			enable_irq_wake(keypad->irq);
 	} else {
 	} else {
 		val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
 		val &= ~SAMSUNG_KEYIFCON_WAKEUPEN;
-		if (device_may_wakeup(dev))
+		if (device_may_wakeup(&keypad->pdev->dev))
 			disable_irq_wake(keypad->irq);
 			disable_irq_wake(keypad->irq);
 	}
 	}
 	writel(val, keypad->base + SAMSUNG_KEYIFCON);
 	writel(val, keypad->base + SAMSUNG_KEYIFCON);
@@ -578,12 +647,13 @@ static int samsung_keypad_resume(struct device *dev)
 
 
 	return 0;
 	return 0;
 }
 }
+#endif
 
 
 static const struct dev_pm_ops samsung_keypad_pm_ops = {
 static const struct dev_pm_ops samsung_keypad_pm_ops = {
-	.suspend	= samsung_keypad_suspend,
-	.resume		= samsung_keypad_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(samsung_keypad_suspend, samsung_keypad_resume)
+	SET_RUNTIME_PM_OPS(samsung_keypad_runtime_suspend,
+			   samsung_keypad_runtime_resume, NULL)
 };
 };
-#endif
 
 
 #ifdef CONFIG_OF
 #ifdef CONFIG_OF
 static const struct of_device_id samsung_keypad_dt_match[] = {
 static const struct of_device_id samsung_keypad_dt_match[] = {
@@ -615,27 +685,13 @@ static struct platform_driver samsung_keypad_driver = {
 		.name	= "samsung-keypad",
 		.name	= "samsung-keypad",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.of_match_table = samsung_keypad_dt_match,
 		.of_match_table = samsung_keypad_dt_match,
-#ifdef CONFIG_PM
 		.pm	= &samsung_keypad_pm_ops,
 		.pm	= &samsung_keypad_pm_ops,
-#endif
 	},
 	},
 	.id_table	= samsung_keypad_driver_ids,
 	.id_table	= samsung_keypad_driver_ids,
 };
 };
-
-static int __init samsung_keypad_init(void)
-{
-	return platform_driver_register(&samsung_keypad_driver);
-}
-module_init(samsung_keypad_init);
-
-static void __exit samsung_keypad_exit(void)
-{
-	platform_driver_unregister(&samsung_keypad_driver);
-}
-module_exit(samsung_keypad_exit);
+module_platform_driver(samsung_keypad_driver);
 
 
 MODULE_DESCRIPTION("Samsung keypad driver");
 MODULE_DESCRIPTION("Samsung keypad driver");
 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
 MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-keypad");

+ 1 - 13
drivers/input/keyboard/sh_keysc.c

@@ -337,19 +337,7 @@ static struct platform_driver sh_keysc_device_driver = {
 		.pm	= &sh_keysc_dev_pm_ops,
 		.pm	= &sh_keysc_dev_pm_ops,
 	}
 	}
 };
 };
-
-static int __init sh_keysc_init(void)
-{
-	return platform_driver_register(&sh_keysc_device_driver);
-}
-
-static void __exit sh_keysc_exit(void)
-{
-	platform_driver_unregister(&sh_keysc_device_driver);
-}
-
-module_init(sh_keysc_init);
-module_exit(sh_keysc_exit);
+module_platform_driver(sh_keysc_device_driver);
 
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");
 MODULE_DESCRIPTION("SuperH KEYSC Keypad Driver");

+ 1 - 12
drivers/input/keyboard/spear-keyboard.c

@@ -326,18 +326,7 @@ static struct platform_driver spear_kbd_driver = {
 #endif
 #endif
 	},
 	},
 };
 };
-
-static int __init spear_kbd_init(void)
-{
-	return platform_driver_register(&spear_kbd_driver);
-}
-module_init(spear_kbd_init);
-
-static void __exit spear_kbd_exit(void)
-{
-	platform_driver_unregister(&spear_kbd_driver);
-}
-module_exit(spear_kbd_exit);
+module_platform_driver(spear_kbd_driver);
 
 
 MODULE_AUTHOR("Rajeev Kumar");
 MODULE_AUTHOR("Rajeev Kumar");
 MODULE_DESCRIPTION("SPEAr Keyboard Driver");
 MODULE_DESCRIPTION("SPEAr Keyboard Driver");

+ 1 - 12
drivers/input/keyboard/stmpe-keypad.c

@@ -368,18 +368,7 @@ static struct platform_driver stmpe_keypad_driver = {
 	.probe		= stmpe_keypad_probe,
 	.probe		= stmpe_keypad_probe,
 	.remove		= __devexit_p(stmpe_keypad_remove),
 	.remove		= __devexit_p(stmpe_keypad_remove),
 };
 };
-
-static int __init stmpe_keypad_init(void)
-{
-	return platform_driver_register(&stmpe_keypad_driver);
-}
-module_init(stmpe_keypad_init);
-
-static void __exit stmpe_keypad_exit(void)
-{
-	platform_driver_unregister(&stmpe_keypad_driver);
-}
-module_exit(stmpe_keypad_exit);
+module_platform_driver(stmpe_keypad_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("STMPExxxx keypad driver");
 MODULE_DESCRIPTION("STMPExxxx keypad driver");

+ 3 - 12
drivers/input/keyboard/tc3589x-keypad.c

@@ -74,11 +74,13 @@
 
 
 /**
 /**
  * struct tc_keypad - data structure used by keypad driver
  * struct tc_keypad - data structure used by keypad driver
+ * @tc3589x:    pointer to tc35893
  * @input:      pointer to input device object
  * @input:      pointer to input device object
  * @board:      keypad platform device
  * @board:      keypad platform device
  * @krow:	number of rows
  * @krow:	number of rows
  * @kcol:	number of coloumns
  * @kcol:	number of coloumns
  * @keymap:     matrix scan code table for keycodes
  * @keymap:     matrix scan code table for keycodes
+ * @keypad_stopped: holds keypad status
  */
  */
 struct tc_keypad {
 struct tc_keypad {
 	struct tc3589x *tc3589x;
 	struct tc3589x *tc3589x;
@@ -453,18 +455,7 @@ static struct platform_driver tc3589x_keypad_driver = {
 	.probe	= tc3589x_keypad_probe,
 	.probe	= tc3589x_keypad_probe,
 	.remove	= __devexit_p(tc3589x_keypad_remove),
 	.remove	= __devexit_p(tc3589x_keypad_remove),
 };
 };
-
-static int __init tc3589x_keypad_init(void)
-{
-	return platform_driver_register(&tc3589x_keypad_driver);
-}
-module_init(tc3589x_keypad_init);
-
-static void __exit tc3589x_keypad_exit(void)
-{
-	return platform_driver_unregister(&tc3589x_keypad_driver);
-}
-module_exit(tc3589x_keypad_exit);
+module_platform_driver(tc3589x_keypad_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");
 MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer");

+ 430 - 0
drivers/input/keyboard/tca8418_keypad.c

@@ -0,0 +1,430 @@
+/*
+ * Driver for TCA8418 I2C keyboard
+ *
+ * Copyright (C) 2011 Fuel7, Inc.  All rights reserved.
+ *
+ * Author: Kyle Manna <kyle.manna@fuel7.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * If you can't comply with GPLv2, alternative licensing terms may be
+ * arranged. Please contact Fuel7, Inc. (http://fuel7.com/) for proprietary
+ * alternative licensing inquiries.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/tca8418_keypad.h>
+
+/* TCA8418 hardware limits */
+#define TCA8418_MAX_ROWS	8
+#define TCA8418_MAX_COLS	10
+
+/* TCA8418 register offsets */
+#define REG_CFG			0x01
+#define REG_INT_STAT		0x02
+#define REG_KEY_LCK_EC		0x03
+#define REG_KEY_EVENT_A		0x04
+#define REG_KEY_EVENT_B		0x05
+#define REG_KEY_EVENT_C		0x06
+#define REG_KEY_EVENT_D		0x07
+#define REG_KEY_EVENT_E		0x08
+#define REG_KEY_EVENT_F		0x09
+#define REG_KEY_EVENT_G		0x0A
+#define REG_KEY_EVENT_H		0x0B
+#define REG_KEY_EVENT_I		0x0C
+#define REG_KEY_EVENT_J		0x0D
+#define REG_KP_LCK_TIMER	0x0E
+#define REG_UNLOCK1		0x0F
+#define REG_UNLOCK2		0x10
+#define REG_GPIO_INT_STAT1	0x11
+#define REG_GPIO_INT_STAT2	0x12
+#define REG_GPIO_INT_STAT3	0x13
+#define REG_GPIO_DAT_STAT1	0x14
+#define REG_GPIO_DAT_STAT2	0x15
+#define REG_GPIO_DAT_STAT3	0x16
+#define REG_GPIO_DAT_OUT1	0x17
+#define REG_GPIO_DAT_OUT2	0x18
+#define REG_GPIO_DAT_OUT3	0x19
+#define REG_GPIO_INT_EN1	0x1A
+#define REG_GPIO_INT_EN2	0x1B
+#define REG_GPIO_INT_EN3	0x1C
+#define REG_KP_GPIO1		0x1D
+#define REG_KP_GPIO2		0x1E
+#define REG_KP_GPIO3		0x1F
+#define REG_GPI_EM1		0x20
+#define REG_GPI_EM2		0x21
+#define REG_GPI_EM3		0x22
+#define REG_GPIO_DIR1		0x23
+#define REG_GPIO_DIR2		0x24
+#define REG_GPIO_DIR3		0x25
+#define REG_GPIO_INT_LVL1	0x26
+#define REG_GPIO_INT_LVL2	0x27
+#define REG_GPIO_INT_LVL3	0x28
+#define REG_DEBOUNCE_DIS1	0x29
+#define REG_DEBOUNCE_DIS2	0x2A
+#define REG_DEBOUNCE_DIS3	0x2B
+#define REG_GPIO_PULL1		0x2C
+#define REG_GPIO_PULL2		0x2D
+#define REG_GPIO_PULL3		0x2E
+
+/* TCA8418 bit definitions */
+#define CFG_AI			BIT(7)
+#define CFG_GPI_E_CFG		BIT(6)
+#define CFG_OVR_FLOW_M		BIT(5)
+#define CFG_INT_CFG		BIT(4)
+#define CFG_OVR_FLOW_IEN	BIT(3)
+#define CFG_K_LCK_IEN		BIT(2)
+#define CFG_GPI_IEN		BIT(1)
+#define CFG_KE_IEN		BIT(0)
+
+#define INT_STAT_CAD_INT	BIT(4)
+#define INT_STAT_OVR_FLOW_INT	BIT(3)
+#define INT_STAT_K_LCK_INT	BIT(2)
+#define INT_STAT_GPI_INT	BIT(1)
+#define INT_STAT_K_INT		BIT(0)
+
+/* TCA8418 register masks */
+#define KEY_LCK_EC_KEC		0x7
+#define KEY_EVENT_CODE		0x7f
+#define KEY_EVENT_VALUE		0x80
+
+
+static const struct i2c_device_id tca8418_id[] = {
+	{ TCA8418_NAME, 8418, },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tca8418_id);
+
+struct tca8418_keypad {
+	unsigned int rows;
+	unsigned int cols;
+	unsigned int keypad_mask; /* Mask for keypad col/rol regs */
+	unsigned int irq;
+	unsigned int row_shift;
+
+	struct i2c_client *client;
+	struct input_dev *input;
+
+	/* Flexible array member, must be at end of struct */
+	unsigned short keymap[];
+};
+
+/*
+ * Write a byte to the TCA8418
+ */
+static int tca8418_write_byte(struct tca8418_keypad *keypad_data,
+			      int reg, u8 val)
+{
+	int error;
+
+	error = i2c_smbus_write_byte_data(keypad_data->client, reg, val);
+	if (error < 0) {
+		dev_err(&keypad_data->client->dev,
+			"%s failed, reg: %d, val: %d, error: %d\n",
+			__func__, reg, val, error);
+		return error;
+	}
+
+	return 0;
+}
+
+/*
+ * Read a byte from the TCA8418
+ */
+static int tca8418_read_byte(struct tca8418_keypad *keypad_data,
+			     int reg, u8 *val)
+{
+	int error;
+
+	error = i2c_smbus_read_byte_data(keypad_data->client, reg);
+	if (error < 0) {
+		dev_err(&keypad_data->client->dev,
+				"%s failed, reg: %d, error: %d\n",
+				__func__, reg, error);
+		return error;
+	}
+
+	*val = (u8)error;
+
+	return 0;
+}
+
+static void tca8418_read_keypad(struct tca8418_keypad *keypad_data)
+{
+	int error, col, row;
+	u8 reg, state, code;
+
+	/* Initial read of the key event FIFO */
+	error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
+
+	/* Assume that key code 0 signifies empty FIFO */
+	while (error >= 0 && reg > 0) {
+		state = reg & KEY_EVENT_VALUE;
+		code  = reg & KEY_EVENT_CODE;
+
+		row = code / TCA8418_MAX_COLS;
+		col = code % TCA8418_MAX_COLS;
+
+		row = (col) ? row : row - 1;
+		col = (col) ? col - 1 : TCA8418_MAX_COLS - 1;
+
+		code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift);
+		input_event(keypad_data->input, EV_MSC, MSC_SCAN, code);
+		input_report_key(keypad_data->input,
+				keypad_data->keymap[code], state);
+
+		/* Read for next loop */
+		error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
+	}
+
+	if (error < 0)
+		dev_err(&keypad_data->client->dev,
+			"unable to read REG_KEY_EVENT_A\n");
+
+	input_sync(keypad_data->input);
+}
+
+/*
+ * Threaded IRQ handler and this can (and will) sleep.
+ */
+static irqreturn_t tca8418_irq_handler(int irq, void *dev_id)
+{
+	struct tca8418_keypad *keypad_data = dev_id;
+	u8 reg;
+	int error;
+
+	error = tca8418_read_byte(keypad_data, REG_INT_STAT, &reg);
+	if (error) {
+		dev_err(&keypad_data->client->dev,
+			"unable to read REG_INT_STAT\n");
+		goto exit;
+	}
+
+	if (reg & INT_STAT_OVR_FLOW_INT)
+		dev_warn(&keypad_data->client->dev, "overflow occurred\n");
+
+	if (reg & INT_STAT_K_INT)
+		tca8418_read_keypad(keypad_data);
+
+exit:
+	/* Clear all interrupts, even IRQs we didn't check (GPI, CAD, LCK) */
+	reg = 0xff;
+	error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg);
+	if (error)
+		dev_err(&keypad_data->client->dev,
+			"unable to clear REG_INT_STAT\n");
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Configure the TCA8418 for keypad operation
+ */
+static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data)
+{
+	int reg, error;
+
+	/* Write config register, if this fails assume device not present */
+	error = tca8418_write_byte(keypad_data, REG_CFG,
+				CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN);
+	if (error < 0)
+		return -ENODEV;
+
+
+	/* Assemble a mask for row and column registers */
+	reg  =  ~(~0 << keypad_data->rows);
+	reg += (~(~0 << keypad_data->cols)) << 8;
+	keypad_data->keypad_mask = reg;
+
+	/* Set registers to keypad mode */
+	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg);
+	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO2, reg >> 8);
+	error |= tca8418_write_byte(keypad_data, REG_KP_GPIO3, reg >> 16);
+
+	/* Enable column debouncing */
+	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS1, reg);
+	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg >> 8);
+	error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg >> 16);
+
+	return error;
+}
+
+static int __devinit tca8418_keypad_probe(struct i2c_client *client,
+					  const struct i2c_device_id *id)
+{
+	const struct tca8418_keypad_platform_data *pdata =
+						client->dev.platform_data;
+	struct tca8418_keypad *keypad_data;
+	struct input_dev *input;
+	int error, row_shift, max_keys;
+
+	/* Copy the platform data */
+	if (!pdata) {
+		dev_dbg(&client->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	if (!pdata->keymap_data) {
+		dev_err(&client->dev, "no keymap data defined\n");
+		return -EINVAL;
+	}
+
+	if (!pdata->rows || pdata->rows > TCA8418_MAX_ROWS) {
+		dev_err(&client->dev, "invalid rows\n");
+		return -EINVAL;
+	}
+
+	if (!pdata->cols || pdata->cols > TCA8418_MAX_COLS) {
+		dev_err(&client->dev, "invalid columns\n");
+		return -EINVAL;
+	}
+
+	/* Check i2c driver capabilities */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
+		dev_err(&client->dev, "%s adapter not supported\n",
+			dev_driver_string(&client->adapter->dev));
+		return -ENODEV;
+	}
+
+	row_shift = get_count_order(pdata->cols);
+	max_keys = pdata->rows << row_shift;
+
+	/* Allocate memory for keypad_data, keymap and input device */
+	keypad_data = kzalloc(sizeof(*keypad_data) +
+			max_keys * sizeof(keypad_data->keymap[0]), GFP_KERNEL);
+	if (!keypad_data)
+		return -ENOMEM;
+
+	keypad_data->rows = pdata->rows;
+	keypad_data->cols = pdata->cols;
+	keypad_data->client = client;
+	keypad_data->row_shift = row_shift;
+
+	/* Initialize the chip or fail if chip isn't present */
+	error = tca8418_configure(keypad_data);
+	if (error < 0)
+		goto fail1;
+
+	/* Configure input device */
+	input = input_allocate_device();
+	if (!input) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+	keypad_data->input = input;
+
+	input->name = client->name;
+	input->dev.parent = &client->dev;
+
+	input->id.bustype = BUS_I2C;
+	input->id.vendor  = 0x0001;
+	input->id.product = 0x001;
+	input->id.version = 0x0001;
+
+	input->keycode     = keypad_data->keymap;
+	input->keycodesize = sizeof(keypad_data->keymap[0]);
+	input->keycodemax  = max_keys;
+
+	__set_bit(EV_KEY, input->evbit);
+	if (pdata->rep)
+		__set_bit(EV_REP, input->evbit);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+
+	input_set_drvdata(input, keypad_data);
+
+	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
+			input->keycode, input->keybit);
+
+	if (pdata->irq_is_gpio)
+		client->irq = gpio_to_irq(client->irq);
+
+	error = request_threaded_irq(client->irq, NULL, tca8418_irq_handler,
+				     IRQF_TRIGGER_FALLING,
+				     client->name, keypad_data);
+	if (error) {
+		dev_dbg(&client->dev,
+			"Unable to claim irq %d; error %d\n",
+			client->irq, error);
+		goto fail2;
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		dev_dbg(&client->dev,
+			"Unable to register input device, error: %d\n", error);
+		goto fail3;
+	}
+
+	i2c_set_clientdata(client, keypad_data);
+	return 0;
+
+fail3:
+	free_irq(client->irq, keypad_data);
+fail2:
+	input_free_device(input);
+fail1:
+	kfree(keypad_data);
+	return error;
+}
+
+static int __devexit tca8418_keypad_remove(struct i2c_client *client)
+{
+	struct tca8418_keypad *keypad_data = i2c_get_clientdata(client);
+
+	free_irq(keypad_data->client->irq, keypad_data);
+
+	input_unregister_device(keypad_data->input);
+
+	kfree(keypad_data);
+
+	return 0;
+}
+
+
+static struct i2c_driver tca8418_keypad_driver = {
+	.driver = {
+		.name	= TCA8418_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tca8418_keypad_probe,
+	.remove		= __devexit_p(tca8418_keypad_remove),
+	.id_table	= tca8418_id,
+};
+
+static int __init tca8418_keypad_init(void)
+{
+	return i2c_add_driver(&tca8418_keypad_driver);
+}
+subsys_initcall(tca8418_keypad_init);
+
+static void __exit tca8418_keypad_exit(void)
+{
+	i2c_del_driver(&tca8418_keypad_driver);
+}
+module_exit(tca8418_keypad_exit);
+
+MODULE_AUTHOR("Kyle Manna <kyle.manna@fuel7.com>");
+MODULE_DESCRIPTION("Keypad driver for TCA8418");
+MODULE_LICENSE("GPL");

+ 109 - 23
drivers/input/keyboard/tegra-kbc.c

@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
+#include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <mach/clk.h>
 #include <mach/clk.h>
@@ -52,6 +53,7 @@
 /* KBC Interrupt Register */
 /* KBC Interrupt Register */
 #define KBC_INT_0	0x4
 #define KBC_INT_0	0x4
 #define KBC_INT_FIFO_CNT_INT_STATUS	(1 << 2)
 #define KBC_INT_FIFO_CNT_INT_STATUS	(1 << 2)
+#define KBC_INT_KEYPRESS_INT_STATUS	(1 << 0)
 
 
 #define KBC_ROW_CFG0_0	0x8
 #define KBC_ROW_CFG0_0	0x8
 #define KBC_COL_CFG0_0	0x18
 #define KBC_COL_CFG0_0	0x18
@@ -74,15 +76,17 @@ struct tegra_kbc {
 	unsigned int cp_to_wkup_dly;
 	unsigned int cp_to_wkup_dly;
 	bool use_fn_map;
 	bool use_fn_map;
 	bool use_ghost_filter;
 	bool use_ghost_filter;
+	bool keypress_caused_wake;
 	const struct tegra_kbc_platform_data *pdata;
 	const struct tegra_kbc_platform_data *pdata;
 	unsigned short keycode[KBC_MAX_KEY * 2];
 	unsigned short keycode[KBC_MAX_KEY * 2];
 	unsigned short current_keys[KBC_MAX_KPENT];
 	unsigned short current_keys[KBC_MAX_KPENT];
 	unsigned int num_pressed_keys;
 	unsigned int num_pressed_keys;
+	u32 wakeup_key;
 	struct timer_list timer;
 	struct timer_list timer;
 	struct clk *clk;
 	struct clk *clk;
 };
 };
 
 
-static const u32 tegra_kbc_default_keymap[] = {
+static const u32 tegra_kbc_default_keymap[] __devinitdata = {
 	KEY(0, 2, KEY_W),
 	KEY(0, 2, KEY_W),
 	KEY(0, 3, KEY_S),
 	KEY(0, 3, KEY_S),
 	KEY(0, 4, KEY_A),
 	KEY(0, 4, KEY_A),
@@ -217,7 +221,8 @@ static const u32 tegra_kbc_default_keymap[] = {
 	KEY(31, 4, KEY_HELP),
 	KEY(31, 4, KEY_HELP),
 };
 };
 
 
-static const struct matrix_keymap_data tegra_kbc_default_keymap_data = {
+static const
+struct matrix_keymap_data tegra_kbc_default_keymap_data __devinitdata = {
 	.keymap		= tegra_kbc_default_keymap,
 	.keymap		= tegra_kbc_default_keymap,
 	.keymap_size	= ARRAY_SIZE(tegra_kbc_default_keymap),
 	.keymap_size	= ARRAY_SIZE(tegra_kbc_default_keymap),
 };
 };
@@ -409,6 +414,9 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args)
 		 */
 		 */
 		tegra_kbc_set_fifo_interrupt(kbc, false);
 		tegra_kbc_set_fifo_interrupt(kbc, false);
 		mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
 		mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies);
+	} else if (val & KBC_INT_KEYPRESS_INT_STATUS) {
+		/* We can be here only through system resume path */
+		kbc->keypress_caused_wake = true;
 	}
 	}
 
 
 	spin_unlock_irqrestore(&kbc->lock, flags);
 	spin_unlock_irqrestore(&kbc->lock, flags);
@@ -576,6 +584,56 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata,
 	return true;
 	return true;
 }
 }
 
 
+#ifdef CONFIG_OF
+static struct tegra_kbc_platform_data * __devinit
+tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
+{
+	struct tegra_kbc_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np)
+		return NULL;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	if (!of_property_read_u32(np, "debounce-delay", &prop))
+		pdata->debounce_cnt = prop;
+
+	if (!of_property_read_u32(np, "repeat-delay", &prop))
+		pdata->repeat_cnt = prop;
+
+	if (of_find_property(np, "needs-ghost-filter", NULL))
+		pdata->use_ghost_filter = true;
+
+	if (of_find_property(np, "wakeup-source", NULL))
+		pdata->wakeup = true;
+
+	/*
+	 * All currently known keymaps with device tree support use the same
+	 * pin_cfg, so set it up here.
+	 */
+	for (i = 0; i < KBC_MAX_ROW; i++) {
+		pdata->pin_cfg[i].num = i;
+		pdata->pin_cfg[i].is_row = true;
+	}
+
+	for (i = 0; i < KBC_MAX_COL; i++) {
+		pdata->pin_cfg[KBC_MAX_ROW + i].num = i;
+		pdata->pin_cfg[KBC_MAX_ROW + i].is_row = false;
+	}
+
+	return pdata;
+}
+#else
+static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata(
+	struct platform_device *pdev)
+{
+	return NULL;
+}
+#endif
+
 static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 {
 {
 	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
 	const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data;
@@ -590,21 +648,28 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 	unsigned int scan_time_rows;
 	unsigned int scan_time_rows;
 
 
 	if (!pdata)
 	if (!pdata)
-		return -EINVAL;
+		pdata = tegra_kbc_dt_parse_pdata(pdev);
 
 
-	if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows))
+	if (!pdata)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) {
+		err = -EINVAL;
+		goto err_free_pdata;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 	if (!res) {
 		dev_err(&pdev->dev, "failed to get I/O memory\n");
 		dev_err(&pdev->dev, "failed to get I/O memory\n");
-		return -ENXIO;
+		err = -ENXIO;
+		goto err_free_pdata;
 	}
 	}
 
 
 	irq = platform_get_irq(pdev, 0);
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 	if (irq < 0) {
 		dev_err(&pdev->dev, "failed to get keyboard IRQ\n");
 		dev_err(&pdev->dev, "failed to get keyboard IRQ\n");
-		return -ENXIO;
+		err = -ENXIO;
+		goto err_free_pdata;
 	}
 	}
 
 
 	kbc = kzalloc(sizeof(*kbc), GFP_KERNEL);
 	kbc = kzalloc(sizeof(*kbc), GFP_KERNEL);
@@ -674,9 +739,10 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev)
 	keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data;
 	keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data;
 	matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT,
 	matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT,
 				   input_dev->keycode, input_dev->keybit);
 				   input_dev->keycode, input_dev->keybit);
+	kbc->wakeup_key = pdata->wakeup_key;
 
 
-	err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH,
-			  pdev->name, kbc);
+	err = request_irq(kbc->irq, tegra_kbc_isr,
+			  IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc);
 	if (err) {
 	if (err) {
 		dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
 		dev_err(&pdev->dev, "failed to request keyboard IRQ\n");
 		goto err_put_clk;
 		goto err_put_clk;
@@ -706,6 +772,9 @@ err_free_mem_region:
 err_free_mem:
 err_free_mem:
 	input_free_device(input_dev);
 	input_free_device(input_dev);
 	kfree(kbc);
 	kfree(kbc);
+err_free_pdata:
+	if (!pdev->dev.platform_data)
+		kfree(pdata);
 
 
 	return err;
 	return err;
 }
 }
@@ -715,6 +784,8 @@ static int __devexit tegra_kbc_remove(struct platform_device *pdev)
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 	struct tegra_kbc *kbc = platform_get_drvdata(pdev);
 	struct resource *res;
 	struct resource *res;
 
 
+	platform_set_drvdata(pdev, NULL);
+
 	free_irq(kbc->irq, pdev);
 	free_irq(kbc->irq, pdev);
 	clk_put(kbc->clk);
 	clk_put(kbc->clk);
 
 
@@ -723,9 +794,14 @@ static int __devexit tegra_kbc_remove(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, resource_size(res));
 	release_mem_region(res->start, resource_size(res));
 
 
-	kfree(kbc);
+	/*
+	 * If we do not have platform data attached to the device we
+	 * allocated it ourselves and thus need to free it.
+	 */
+	if (!pdev->dev.platform_data)
+		kfree(kbc->pdata);
 
 
-	platform_set_drvdata(pdev, NULL);
+	kfree(kbc);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -754,6 +830,8 @@ static int tegra_kbc_suspend(struct device *dev)
 		tegra_kbc_setup_wakekeys(kbc, true);
 		tegra_kbc_setup_wakekeys(kbc, true);
 		msleep(30);
 		msleep(30);
 
 
+		kbc->keypress_caused_wake = false;
+		enable_irq(kbc->irq);
 		enable_irq_wake(kbc->irq);
 		enable_irq_wake(kbc->irq);
 	} else {
 	} else {
 		if (kbc->idev->users)
 		if (kbc->idev->users)
@@ -780,7 +858,19 @@ static int tegra_kbc_resume(struct device *dev)
 
 
 		tegra_kbc_set_fifo_interrupt(kbc, true);
 		tegra_kbc_set_fifo_interrupt(kbc, true);
 
 
-		enable_irq(kbc->irq);
+		if (kbc->keypress_caused_wake && kbc->wakeup_key) {
+			/*
+			 * We can't report events directly from the ISR
+			 * because timekeeping is stopped when processing
+			 * wakeup request and we get a nasty warning when
+			 * we try to call do_gettimeofday() in evdev
+			 * handler.
+			 */
+			input_report_key(kbc->idev, kbc->wakeup_key, 1);
+			input_sync(kbc->idev);
+			input_report_key(kbc->idev, kbc->wakeup_key, 0);
+			input_sync(kbc->idev);
+		}
 	} else {
 	} else {
 		if (kbc->idev->users)
 		if (kbc->idev->users)
 			err = tegra_kbc_start(kbc);
 			err = tegra_kbc_start(kbc);
@@ -793,6 +883,12 @@ static int tegra_kbc_resume(struct device *dev)
 
 
 static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
 static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
 
 
+static const struct of_device_id tegra_kbc_of_match[] = {
+	{ .compatible = "nvidia,tegra20-kbc", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_kbc_of_match);
+
 static struct platform_driver tegra_kbc_driver = {
 static struct platform_driver tegra_kbc_driver = {
 	.probe		= tegra_kbc_probe,
 	.probe		= tegra_kbc_probe,
 	.remove		= __devexit_p(tegra_kbc_remove),
 	.remove		= __devexit_p(tegra_kbc_remove),
@@ -800,20 +896,10 @@ static struct platform_driver tegra_kbc_driver = {
 		.name	= "tegra-kbc",
 		.name	= "tegra-kbc",
 		.owner  = THIS_MODULE,
 		.owner  = THIS_MODULE,
 		.pm	= &tegra_kbc_pm_ops,
 		.pm	= &tegra_kbc_pm_ops,
+		.of_match_table = tegra_kbc_of_match,
 	},
 	},
 };
 };
-
-static void __exit tegra_kbc_exit(void)
-{
-	platform_driver_unregister(&tegra_kbc_driver);
-}
-module_exit(tegra_kbc_exit);
-
-static int __init tegra_kbc_init(void)
-{
-	return platform_driver_register(&tegra_kbc_driver);
-}
-module_init(tegra_kbc_init);
+module_platform_driver(tegra_kbc_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rakesh Iyer <riyer@nvidia.com>");
 MODULE_AUTHOR("Rakesh Iyer <riyer@nvidia.com>");

+ 1 - 13
drivers/input/keyboard/tnetv107x-keypad.c

@@ -322,19 +322,7 @@ static struct platform_driver keypad_driver = {
 	.driver.name	= "tnetv107x-keypad",
 	.driver.name	= "tnetv107x-keypad",
 	.driver.owner	= THIS_MODULE,
 	.driver.owner	= THIS_MODULE,
 };
 };
-
-static int __init keypad_init(void)
-{
-	return platform_driver_register(&keypad_driver);
-}
-
-static void __exit keypad_exit(void)
-{
-	platform_driver_unregister(&keypad_driver);
-}
-
-module_init(keypad_init);
-module_exit(keypad_exit);
+module_platform_driver(keypad_driver);
 
 
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_AUTHOR("Cyril Chemparathy");
 MODULE_DESCRIPTION("TNETV107X Keypad Driver");
 MODULE_DESCRIPTION("TNETV107X Keypad Driver");

+ 1 - 12
drivers/input/keyboard/twl4030_keypad.c

@@ -460,18 +460,7 @@ static struct platform_driver twl4030_kp_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init twl4030_kp_init(void)
-{
-	return platform_driver_register(&twl4030_kp_driver);
-}
-module_init(twl4030_kp_init);
-
-static void __exit twl4030_kp_exit(void)
-{
-	platform_driver_unregister(&twl4030_kp_driver);
-}
-module_exit(twl4030_kp_exit);
+module_platform_driver(twl4030_kp_driver);
 
 
 MODULE_AUTHOR("Texas Instruments");
 MODULE_AUTHOR("Texas Instruments");
 MODULE_DESCRIPTION("TWL4030 Keypad Driver");
 MODULE_DESCRIPTION("TWL4030 Keypad Driver");

+ 1 - 13
drivers/input/keyboard/w90p910_keypad.c

@@ -262,19 +262,7 @@ static struct platform_driver w90p910_keypad_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init w90p910_keypad_init(void)
-{
-	return platform_driver_register(&w90p910_keypad_driver);
-}
-
-static void __exit w90p910_keypad_exit(void)
-{
-	platform_driver_unregister(&w90p910_keypad_driver);
-}
-
-module_init(w90p910_keypad_init);
-module_exit(w90p910_keypad_exit);
+module_platform_driver(w90p910_keypad_driver);
 
 
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("w90p910 keypad driver");
 MODULE_DESCRIPTION("w90p910 keypad driver");

+ 1 - 12
drivers/input/misc/88pm860x_onkey.c

@@ -137,18 +137,7 @@ static struct platform_driver pm860x_onkey_driver = {
 	.probe		= pm860x_onkey_probe,
 	.probe		= pm860x_onkey_probe,
 	.remove		= __devexit_p(pm860x_onkey_remove),
 	.remove		= __devexit_p(pm860x_onkey_remove),
 };
 };
-
-static int __init pm860x_onkey_init(void)
-{
-	return platform_driver_register(&pm860x_onkey_driver);
-}
-module_init(pm860x_onkey_init);
-
-static void __exit pm860x_onkey_exit(void)
-{
-	platform_driver_unregister(&pm860x_onkey_driver);
-}
-module_exit(pm860x_onkey_exit);
+module_platform_driver(pm860x_onkey_driver);
 
 
 MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
 MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");

+ 25 - 0
drivers/input/misc/Kconfig

@@ -179,6 +179,31 @@ config INPUT_APANEL
 	 To compile this driver as a module, choose M here: the module will
 	 To compile this driver as a module, choose M here: the module will
 	 be called apanel.
 	 be called apanel.
 
 
+config INPUT_GP2A
+	tristate "Sharp GP2AP002A00F I2C Proximity/Opto sensor driver"
+	depends on I2C
+	depends on GENERIC_GPIO
+	help
+	  Say Y here if you have a Sharp GP2AP002A00F proximity/als combo-chip
+	  hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gp2ap002a00f.
+
+config INPUT_GPIO_TILT_POLLED
+	tristate "Polled GPIO tilt switch"
+	depends on GENERIC_GPIO
+	select INPUT_POLLDEV
+	help
+	  This driver implements support for tilt switches connected
+	  to GPIO pins that are not capable of generating interrupts.
+
+	  The list of gpios to use and the mapping of their states
+	  to specific angles is done via platform data.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gpio_tilt_polled.
+
 config INPUT_IXP4XX_BEEPER
 config INPUT_IXP4XX_BEEPER
 	tristate "IXP4XX Beeper support"
 	tristate "IXP4XX Beeper support"
 	depends on ARCH_IXP4XX
 	depends on ARCH_IXP4XX

+ 2 - 0
drivers/input/misc/Makefile

@@ -22,6 +22,8 @@ obj-$(CONFIG_INPUT_CMA3000)		+= cma3000_d0x.o
 obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
 obj-$(CONFIG_INPUT_CMA3000_I2C)		+= cma3000_d0x_i2c.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_COBALT_BTNS)		+= cobalt_btns.o
 obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
 obj-$(CONFIG_INPUT_DM355EVM)		+= dm355evm_keys.o
+obj-$(CONFIG_INPUT_GP2A)		+= gp2ap002a00f.o
+obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)	+= gpio_tilt_polled.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o
 obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)	+= keyspan_remote.o

+ 1 - 12
drivers/input/misc/ab8500-ponkey.c

@@ -139,18 +139,7 @@ static struct platform_driver ab8500_ponkey_driver = {
 	.probe		= ab8500_ponkey_probe,
 	.probe		= ab8500_ponkey_probe,
 	.remove		= __devexit_p(ab8500_ponkey_remove),
 	.remove		= __devexit_p(ab8500_ponkey_remove),
 };
 };
-
-static int __init ab8500_ponkey_init(void)
-{
-	return platform_driver_register(&ab8500_ponkey_driver);
-}
-module_init(ab8500_ponkey_init);
-
-static void __exit ab8500_ponkey_exit(void)
-{
-	platform_driver_unregister(&ab8500_ponkey_driver);
-}
-module_exit(ab8500_ponkey_exit);
+module_platform_driver(ab8500_ponkey_driver);
 
 
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
 MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");

+ 0 - 1
drivers/input/misc/adxl34x-spi.c

@@ -122,7 +122,6 @@ static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
 static struct spi_driver adxl34x_driver = {
 static struct spi_driver adxl34x_driver = {
 	.driver = {
 	.driver = {
 		.name = "adxl34x",
 		.name = "adxl34x",
-		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
 		.owner = THIS_MODULE,
 		.pm = &adxl34x_spi_pm,
 		.pm = &adxl34x_spi_pm,
 	},
 	},

+ 8 - 8
drivers/input/misc/adxl34x.c

@@ -452,10 +452,10 @@ static ssize_t adxl34x_disable_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct adxl34x *ac = dev_get_drvdata(dev);
 	struct adxl34x *ac = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -541,10 +541,10 @@ static ssize_t adxl34x_rate_store(struct device *dev,
 				  const char *buf, size_t count)
 				  const char *buf, size_t count)
 {
 {
 	struct adxl34x *ac = dev_get_drvdata(dev);
 	struct adxl34x *ac = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned char val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtou8(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -576,10 +576,10 @@ static ssize_t adxl34x_autosleep_store(struct device *dev,
 				  const char *buf, size_t count)
 				  const char *buf, size_t count)
 {
 {
 	struct adxl34x *ac = dev_get_drvdata(dev);
 	struct adxl34x *ac = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -623,13 +623,13 @@ static ssize_t adxl34x_write_store(struct device *dev,
 				   const char *buf, size_t count)
 				   const char *buf, size_t count)
 {
 {
 	struct adxl34x *ac = dev_get_drvdata(dev);
 	struct adxl34x *ac = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
 	/*
 	/*
 	 * This allows basic ADXL register write access for debug purposes.
 	 * This allows basic ADXL register write access for debug purposes.
 	 */
 	 */
-	error = strict_strtoul(buf, 16, &val);
+	error = kstrtouint(buf, 16, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 

+ 11 - 8
drivers/input/misc/ati_remote2.c

@@ -42,13 +42,13 @@ static int ati_remote2_set_mask(const char *val,
 				const struct kernel_param *kp,
 				const struct kernel_param *kp,
 				unsigned int max)
 				unsigned int max)
 {
 {
-	unsigned long mask;
+	unsigned int mask;
 	int ret;
 	int ret;
 
 
 	if (!val)
 	if (!val)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	ret = strict_strtoul(val, 0, &mask);
+	ret = kstrtouint(val, 0, &mask);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
@@ -720,11 +720,12 @@ static ssize_t ati_remote2_store_channel_mask(struct device *dev,
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
 	struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
 	struct ati_remote2 *ar2 = usb_get_intfdata(intf);
 	struct ati_remote2 *ar2 = usb_get_intfdata(intf);
-	unsigned long mask;
+	unsigned int mask;
 	int r;
 	int r;
 
 
-	if (strict_strtoul(buf, 0, &mask))
-		return -EINVAL;
+	r = kstrtouint(buf, 0, &mask);
+	if (r)
+		return r;
 
 
 	if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK)
 	if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK)
 		return -EINVAL;
 		return -EINVAL;
@@ -769,10 +770,12 @@ static ssize_t ati_remote2_store_mode_mask(struct device *dev,
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_device *udev = to_usb_device(dev);
 	struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
 	struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
 	struct ati_remote2 *ar2 = usb_get_intfdata(intf);
 	struct ati_remote2 *ar2 = usb_get_intfdata(intf);
-	unsigned long mask;
+	unsigned int mask;
+	int err;
 
 
-	if (strict_strtoul(buf, 0, &mask))
-		return -EINVAL;
+	err = kstrtouint(buf, 0, &mask);
+	if (err)
+		return err;
 
 
 	if (mask & ~ATI_REMOTE2_MAX_MODE_MASK)
 	if (mask & ~ATI_REMOTE2_MAX_MODE_MASK)
 		return -EINVAL;
 		return -EINVAL;

+ 1 - 12
drivers/input/misc/bfin_rotary.c

@@ -264,18 +264,7 @@ static struct platform_driver bfin_rotary_device_driver = {
 #endif
 #endif
 	},
 	},
 };
 };
-
-static int __init bfin_rotary_init(void)
-{
-	return platform_driver_register(&bfin_rotary_device_driver);
-}
-module_init(bfin_rotary_init);
-
-static void __exit bfin_rotary_exit(void)
-{
-	platform_driver_unregister(&bfin_rotary_device_driver);
-}
-module_exit(bfin_rotary_exit);
+module_platform_driver(bfin_rotary_device_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");

+ 1 - 13
drivers/input/misc/cobalt_btns.c

@@ -163,16 +163,4 @@ static struct platform_driver cobalt_buttons_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init cobalt_buttons_init(void)
-{
-	return platform_driver_register(&cobalt_buttons_driver);
-}
-
-static void __exit cobalt_buttons_exit(void)
-{
-	platform_driver_unregister(&cobalt_buttons_driver);
-}
-
-module_init(cobalt_buttons_init);
-module_exit(cobalt_buttons_exit);
+module_platform_driver(cobalt_buttons_driver);

+ 1 - 12
drivers/input/misc/dm355evm_keys.c

@@ -267,17 +267,6 @@ static struct platform_driver dm355evm_keys_driver = {
 		.name	= "dm355evm_keys",
 		.name	= "dm355evm_keys",
 	},
 	},
 };
 };
-
-static int __init dm355evm_keys_init(void)
-{
-	return platform_driver_register(&dm355evm_keys_driver);
-}
-module_init(dm355evm_keys_init);
-
-static void __exit dm355evm_keys_exit(void)
-{
-	platform_driver_unregister(&dm355evm_keys_driver);
-}
-module_exit(dm355evm_keys_exit);
+module_platform_driver(dm355evm_keys_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 299 - 0
drivers/input/misc/gp2ap002a00f.c

@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2011 Sony Ericsson Mobile Communications Inc.
+ *
+ * Author: Courtney Cavin <courtney.cavin@sonyericsson.com>
+ * Prepared for up-stream by: Oskar Andero <oskar.andero@sonyericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/input/gp2ap002a00f.h>
+
+struct gp2a_data {
+	struct input_dev *input;
+	const struct gp2a_platform_data *pdata;
+	struct i2c_client *i2c_client;
+};
+
+enum gp2a_addr {
+	GP2A_ADDR_PROX	= 0x0,
+	GP2A_ADDR_GAIN	= 0x1,
+	GP2A_ADDR_HYS	= 0x2,
+	GP2A_ADDR_CYCLE	= 0x3,
+	GP2A_ADDR_OPMOD	= 0x4,
+	GP2A_ADDR_CON	= 0x6
+};
+
+enum gp2a_controls {
+	/* Software Shutdown control: 0 = shutdown, 1 = normal operation */
+	GP2A_CTRL_SSD	= 0x01
+};
+
+static int gp2a_report(struct gp2a_data *dt)
+{
+	int vo = gpio_get_value(dt->pdata->vout_gpio);
+
+	input_report_switch(dt->input, SW_FRONT_PROXIMITY, !vo);
+	input_sync(dt->input);
+
+	return 0;
+}
+
+static irqreturn_t gp2a_irq(int irq, void *handle)
+{
+	struct gp2a_data *dt = handle;
+
+	gp2a_report(dt);
+
+	return IRQ_HANDLED;
+}
+
+static int gp2a_enable(struct gp2a_data *dt)
+{
+	return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
+					 GP2A_CTRL_SSD);
+}
+
+static int gp2a_disable(struct gp2a_data *dt)
+{
+	return i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_OPMOD,
+					 0x00);
+}
+
+static int gp2a_device_open(struct input_dev *dev)
+{
+	struct gp2a_data *dt = input_get_drvdata(dev);
+	int error;
+
+	error = gp2a_enable(dt);
+	if (error < 0) {
+		dev_err(&dt->i2c_client->dev,
+			"unable to activate, err %d\n", error);
+		return error;
+	}
+
+	gp2a_report(dt);
+
+	return 0;
+}
+
+static void gp2a_device_close(struct input_dev *dev)
+{
+	struct gp2a_data *dt = input_get_drvdata(dev);
+	int error;
+
+	error = gp2a_disable(dt);
+	if (error < 0)
+		dev_err(&dt->i2c_client->dev,
+			"unable to deactivate, err %d\n", error);
+}
+
+static int __devinit gp2a_initialize(struct gp2a_data *dt)
+{
+	int error;
+
+	error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_GAIN,
+					  0x08);
+	if (error < 0)
+		return error;
+
+	error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_HYS,
+					  0xc2);
+	if (error < 0)
+		return error;
+
+	error = i2c_smbus_write_byte_data(dt->i2c_client, GP2A_ADDR_CYCLE,
+					  0x04);
+	if (error < 0)
+		return error;
+
+	error = gp2a_disable(dt);
+
+	return error;
+}
+
+static int __devinit gp2a_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	const struct gp2a_platform_data *pdata = client->dev.platform_data;
+	struct gp2a_data *dt;
+	int error;
+
+	if (!pdata)
+		return -EINVAL;
+
+	if (pdata->hw_setup) {
+		error = pdata->hw_setup(client);
+		if (error < 0)
+			return error;
+	}
+
+	error = gpio_request_one(pdata->vout_gpio, GPIOF_IN, GP2A_I2C_NAME);
+	if (error)
+		goto err_hw_shutdown;
+
+	dt = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
+	if (!dt) {
+		error = -ENOMEM;
+		goto err_free_gpio;
+	}
+
+	dt->pdata = pdata;
+	dt->i2c_client = client;
+
+	error = gp2a_initialize(dt);
+	if (error < 0)
+		goto err_free_mem;
+
+	dt->input = input_allocate_device();
+	if (!dt->input) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	input_set_drvdata(dt->input, dt);
+
+	dt->input->open = gp2a_device_open;
+	dt->input->close = gp2a_device_close;
+	dt->input->name = GP2A_I2C_NAME;
+	dt->input->id.bustype = BUS_I2C;
+	dt->input->dev.parent = &client->dev;
+
+	input_set_capability(dt->input, EV_SW, SW_FRONT_PROXIMITY);
+
+	error = request_threaded_irq(client->irq, NULL, gp2a_irq,
+			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+				IRQF_ONESHOT,
+			GP2A_I2C_NAME, dt);
+	if (error) {
+		dev_err(&client->dev, "irq request failed\n");
+		goto err_free_input_dev;
+	}
+
+	error = input_register_device(dt->input);
+	if (error) {
+		dev_err(&client->dev, "device registration failed\n");
+		goto err_free_irq;
+	}
+
+	device_init_wakeup(&client->dev, pdata->wakeup);
+	i2c_set_clientdata(client, dt);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, dt);
+err_free_input_dev:
+	input_free_device(dt->input);
+err_free_mem:
+	kfree(dt);
+err_free_gpio:
+	gpio_free(pdata->vout_gpio);
+err_hw_shutdown:
+	if (pdata->hw_shutdown)
+		pdata->hw_shutdown(client);
+	return error;
+}
+
+static int __devexit gp2a_remove(struct i2c_client *client)
+{
+	struct gp2a_data *dt = i2c_get_clientdata(client);
+	const struct gp2a_platform_data *pdata = dt->pdata;
+
+	device_init_wakeup(&client->dev, false);
+
+	free_irq(client->irq, dt);
+
+	input_unregister_device(dt->input);
+	kfree(dt);
+
+	gpio_free(pdata->vout_gpio);
+
+	if (pdata->hw_shutdown)
+		pdata->hw_shutdown(client);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int gp2a_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gp2a_data *dt = i2c_get_clientdata(client);
+	int retval = 0;
+
+	if (device_may_wakeup(&client->dev)) {
+		enable_irq_wake(client->irq);
+	} else {
+		mutex_lock(&dt->input->mutex);
+		if (dt->input->users)
+			retval = gp2a_disable(dt);
+		mutex_unlock(&dt->input->mutex);
+	}
+
+	return retval;
+}
+
+static int gp2a_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gp2a_data *dt = i2c_get_clientdata(client);
+	int retval = 0;
+
+	if (device_may_wakeup(&client->dev)) {
+		disable_irq_wake(client->irq);
+	} else {
+		mutex_lock(&dt->input->mutex);
+		if (dt->input->users)
+			retval = gp2a_enable(dt);
+		mutex_unlock(&dt->input->mutex);
+	}
+
+	return retval;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(gp2a_pm, gp2a_suspend, gp2a_resume);
+
+static const struct i2c_device_id gp2a_i2c_id[] = {
+	{ GP2A_I2C_NAME, 0 },
+	{ }
+};
+
+static struct i2c_driver gp2a_i2c_driver = {
+	.driver = {
+		.name	= GP2A_I2C_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= &gp2a_pm,
+	},
+	.probe		= gp2a_probe,
+	.remove		= __devexit_p(gp2a_remove),
+	.id_table	= gp2a_i2c_id,
+};
+
+static int __init gp2a_init(void)
+{
+	return i2c_add_driver(&gp2a_i2c_driver);
+}
+
+static void __exit gp2a_exit(void)
+{
+	i2c_del_driver(&gp2a_i2c_driver);
+}
+
+module_init(gp2a_init);
+module_exit(gp2a_exit);
+
+MODULE_AUTHOR("Courtney Cavin <courtney.cavin@sonyericsson.com>");
+MODULE_DESCRIPTION("Sharp GP2AP002A00F I2C Proximity/Opto sensor driver");
+MODULE_LICENSE("GPL v2");

+ 213 - 0
drivers/input/misc/gpio_tilt_polled.c

@@ -0,0 +1,213 @@
+/*
+ *  Driver for tilt switches connected via GPIO lines
+ *  not capable of generating interrupts
+ *
+ *  Copyright (C) 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ *  based on: drivers/input/keyboard/gpio_keys_polled.c
+ *
+ *  Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input/gpio_tilt.h>
+
+#define DRV_NAME	"gpio-tilt-polled"
+
+struct gpio_tilt_polled_dev {
+	struct input_polled_dev *poll_dev;
+	struct device *dev;
+	const struct gpio_tilt_platform_data *pdata;
+
+	int last_state;
+
+	int threshold;
+	int count;
+};
+
+static void gpio_tilt_polled_poll(struct input_polled_dev *dev)
+{
+	struct gpio_tilt_polled_dev *tdev = dev->private;
+	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
+	struct input_dev *input = dev->input;
+	struct gpio_tilt_state *tilt_state = NULL;
+	int state, i;
+
+	if (tdev->count < tdev->threshold) {
+		tdev->count++;
+	} else {
+		state = 0;
+		for (i = 0; i < pdata->nr_gpios; i++)
+			state |= (!!gpio_get_value(pdata->gpios[i].gpio) << i);
+
+		if (state != tdev->last_state) {
+			for (i = 0; i < pdata->nr_states; i++)
+				if (pdata->states[i].gpios == state)
+					tilt_state = &pdata->states[i];
+
+			if (tilt_state) {
+				for (i = 0; i < pdata->nr_axes; i++)
+					input_report_abs(input,
+							 pdata->axes[i].axis,
+							 tilt_state->axes[i]);
+
+				input_sync(input);
+			}
+
+			tdev->count = 0;
+			tdev->last_state = state;
+		}
+	}
+}
+
+static void gpio_tilt_polled_open(struct input_polled_dev *dev)
+{
+	struct gpio_tilt_polled_dev *tdev = dev->private;
+	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
+
+	if (pdata->enable)
+		pdata->enable(tdev->dev);
+
+	/* report initial state of the axes */
+	tdev->last_state = -1;
+	tdev->count = tdev->threshold;
+	gpio_tilt_polled_poll(tdev->poll_dev);
+}
+
+static void gpio_tilt_polled_close(struct input_polled_dev *dev)
+{
+	struct gpio_tilt_polled_dev *tdev = dev->private;
+	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
+
+	if (pdata->disable)
+		pdata->disable(tdev->dev);
+}
+
+static int __devinit gpio_tilt_polled_probe(struct platform_device *pdev)
+{
+	const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct gpio_tilt_polled_dev *tdev;
+	struct input_polled_dev *poll_dev;
+	struct input_dev *input;
+	int error, i;
+
+	if (!pdata || !pdata->poll_interval)
+		return -EINVAL;
+
+	tdev = kzalloc(sizeof(struct gpio_tilt_polled_dev), GFP_KERNEL);
+	if (!tdev) {
+		dev_err(dev, "no memory for private data\n");
+		return -ENOMEM;
+	}
+
+	error = gpio_request_array(pdata->gpios, pdata->nr_gpios);
+	if (error) {
+		dev_err(dev,
+			"Could not request tilt GPIOs: %d\n", error);
+		goto err_free_tdev;
+	}
+
+	poll_dev = input_allocate_polled_device();
+	if (!poll_dev) {
+		dev_err(dev, "no memory for polled device\n");
+		error = -ENOMEM;
+		goto err_free_gpios;
+	}
+
+	poll_dev->private = tdev;
+	poll_dev->poll = gpio_tilt_polled_poll;
+	poll_dev->poll_interval = pdata->poll_interval;
+	poll_dev->open = gpio_tilt_polled_open;
+	poll_dev->close = gpio_tilt_polled_close;
+
+	input = poll_dev->input;
+
+	input->name = pdev->name;
+	input->phys = DRV_NAME"/input0";
+	input->dev.parent = &pdev->dev;
+
+	input->id.bustype = BUS_HOST;
+	input->id.vendor = 0x0001;
+	input->id.product = 0x0001;
+	input->id.version = 0x0100;
+
+	__set_bit(EV_ABS, input->evbit);
+	for (i = 0; i < pdata->nr_axes; i++)
+		input_set_abs_params(input, pdata->axes[i].axis,
+				     pdata->axes[i].min, pdata->axes[i].max,
+				     pdata->axes[i].fuzz, pdata->axes[i].flat);
+
+	tdev->threshold = DIV_ROUND_UP(pdata->debounce_interval,
+				       pdata->poll_interval);
+
+	tdev->poll_dev = poll_dev;
+	tdev->dev = dev;
+	tdev->pdata = pdata;
+
+	error = input_register_polled_device(poll_dev);
+	if (error) {
+		dev_err(dev, "unable to register polled device, err=%d\n",
+			error);
+		goto err_free_polldev;
+	}
+
+	platform_set_drvdata(pdev, tdev);
+
+	return 0;
+
+err_free_polldev:
+	input_free_polled_device(poll_dev);
+err_free_gpios:
+	gpio_free_array(pdata->gpios, pdata->nr_gpios);
+err_free_tdev:
+	kfree(tdev);
+
+	return error;
+}
+
+static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev)
+{
+	struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev);
+	const struct gpio_tilt_platform_data *pdata = tdev->pdata;
+
+	platform_set_drvdata(pdev, NULL);
+
+	input_unregister_polled_device(tdev->poll_dev);
+	input_free_polled_device(tdev->poll_dev);
+
+	gpio_free_array(pdata->gpios, pdata->nr_gpios);
+
+	kfree(tdev);
+
+	return 0;
+}
+
+static struct platform_driver gpio_tilt_polled_driver = {
+	.probe	= gpio_tilt_polled_probe,
+	.remove	= __devexit_p(gpio_tilt_polled_remove),
+	.driver	= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpio_tilt_polled_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
+MODULE_DESCRIPTION("Polled GPIO tilt driver");
+MODULE_ALIAS("platform:" DRV_NAME);

+ 1 - 12
drivers/input/misc/ixp4xx-beeper.c

@@ -168,16 +168,5 @@ static struct platform_driver ixp4xx_spkr_platform_driver = {
 	.remove		= __devexit_p(ixp4xx_spkr_remove),
 	.remove		= __devexit_p(ixp4xx_spkr_remove),
 	.shutdown	= ixp4xx_spkr_shutdown,
 	.shutdown	= ixp4xx_spkr_shutdown,
 };
 };
+module_platform_driver(ixp4xx_spkr_platform_driver);
 
 
-static int __init ixp4xx_spkr_init(void)
-{
-	return platform_driver_register(&ixp4xx_spkr_platform_driver);
-}
-
-static void __exit ixp4xx_spkr_exit(void)
-{
-	platform_driver_unregister(&ixp4xx_spkr_platform_driver);
-}
-
-module_init(ixp4xx_spkr_init);
-module_exit(ixp4xx_spkr_exit);

+ 1 - 12
drivers/input/misc/max8925_onkey.c

@@ -166,18 +166,7 @@ static struct platform_driver max8925_onkey_driver = {
 	.probe		= max8925_onkey_probe,
 	.probe		= max8925_onkey_probe,
 	.remove		= __devexit_p(max8925_onkey_remove),
 	.remove		= __devexit_p(max8925_onkey_remove),
 };
 };
-
-static int __init max8925_onkey_init(void)
-{
-	return platform_driver_register(&max8925_onkey_driver);
-}
-module_init(max8925_onkey_init);
-
-static void __exit max8925_onkey_exit(void)
-{
-	platform_driver_unregister(&max8925_onkey_driver);
-}
-module_exit(max8925_onkey_exit);
+module_platform_driver(max8925_onkey_driver);
 
 
 MODULE_DESCRIPTION("Maxim MAX8925 ONKEY driver");
 MODULE_DESCRIPTION("Maxim MAX8925 ONKEY driver");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");

+ 2 - 12
drivers/input/misc/mc13783-pwrbutton.c

@@ -255,7 +255,7 @@ static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-struct platform_driver mc13783_pwrbutton_driver = {
+static struct platform_driver mc13783_pwrbutton_driver = {
 	.probe		= mc13783_pwrbutton_probe,
 	.probe		= mc13783_pwrbutton_probe,
 	.remove		= __devexit_p(mc13783_pwrbutton_remove),
 	.remove		= __devexit_p(mc13783_pwrbutton_remove),
 	.driver		= {
 	.driver		= {
@@ -264,17 +264,7 @@ struct platform_driver mc13783_pwrbutton_driver = {
 	},
 	},
 };
 };
 
 
-static int __init mc13783_pwrbutton_init(void)
-{
-	return platform_driver_register(&mc13783_pwrbutton_driver);
-}
-module_init(mc13783_pwrbutton_init);
-
-static void __exit mc13783_pwrbutton_exit(void)
-{
-	platform_driver_unregister(&mc13783_pwrbutton_driver);
-}
-module_exit(mc13783_pwrbutton_exit);
+module_platform_driver(mc13783_pwrbutton_driver);
 
 
 MODULE_ALIAS("platform:mc13783-pwrbutton");
 MODULE_ALIAS("platform:mc13783-pwrbutton");
 MODULE_DESCRIPTION("MC13783 Power Button");
 MODULE_DESCRIPTION("MC13783 Power Button");

+ 122 - 6
drivers/input/misc/mpu3050.c

@@ -41,18 +41,67 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 
 
-#define MPU3050_CHIP_ID_REG	0x00
 #define MPU3050_CHIP_ID		0x69
 #define MPU3050_CHIP_ID		0x69
-#define MPU3050_XOUT_H		0x1D
-#define MPU3050_PWR_MGM		0x3E
-#define MPU3050_PWR_MGM_POS	6
-#define MPU3050_PWR_MGM_MASK	0x40
 
 
 #define MPU3050_AUTO_DELAY	1000
 #define MPU3050_AUTO_DELAY	1000
 
 
 #define MPU3050_MIN_VALUE	-32768
 #define MPU3050_MIN_VALUE	-32768
 #define MPU3050_MAX_VALUE	32767
 #define MPU3050_MAX_VALUE	32767
 
 
+#define MPU3050_DEFAULT_POLL_INTERVAL	200
+#define MPU3050_DEFAULT_FS_RANGE	3
+
+/* Register map */
+#define MPU3050_CHIP_ID_REG	0x00
+#define MPU3050_SMPLRT_DIV	0x15
+#define MPU3050_DLPF_FS_SYNC	0x16
+#define MPU3050_INT_CFG		0x17
+#define MPU3050_XOUT_H		0x1D
+#define MPU3050_PWR_MGM		0x3E
+#define MPU3050_PWR_MGM_POS	6
+
+/* Register bits */
+
+/* DLPF_FS_SYNC */
+#define MPU3050_EXT_SYNC_NONE		0x00
+#define MPU3050_EXT_SYNC_TEMP		0x20
+#define MPU3050_EXT_SYNC_GYROX		0x40
+#define MPU3050_EXT_SYNC_GYROY		0x60
+#define MPU3050_EXT_SYNC_GYROZ		0x80
+#define MPU3050_EXT_SYNC_ACCELX	0xA0
+#define MPU3050_EXT_SYNC_ACCELY	0xC0
+#define MPU3050_EXT_SYNC_ACCELZ	0xE0
+#define MPU3050_EXT_SYNC_MASK		0xE0
+#define MPU3050_FS_250DPS		0x00
+#define MPU3050_FS_500DPS		0x08
+#define MPU3050_FS_1000DPS		0x10
+#define MPU3050_FS_2000DPS		0x18
+#define MPU3050_FS_MASK		0x18
+#define MPU3050_DLPF_CFG_256HZ_NOLPF2	0x00
+#define MPU3050_DLPF_CFG_188HZ		0x01
+#define MPU3050_DLPF_CFG_98HZ		0x02
+#define MPU3050_DLPF_CFG_42HZ		0x03
+#define MPU3050_DLPF_CFG_20HZ		0x04
+#define MPU3050_DLPF_CFG_10HZ		0x05
+#define MPU3050_DLPF_CFG_5HZ		0x06
+#define MPU3050_DLPF_CFG_2100HZ_NOLPF	0x07
+#define MPU3050_DLPF_CFG_MASK		0x07
+/* INT_CFG */
+#define MPU3050_RAW_RDY_EN		0x01
+#define MPU3050_MPU_RDY_EN		0x02
+#define MPU3050_LATCH_INT_EN		0x04
+/* PWR_MGM */
+#define MPU3050_PWR_MGM_PLL_X		0x01
+#define MPU3050_PWR_MGM_PLL_Y		0x02
+#define MPU3050_PWR_MGM_PLL_Z		0x03
+#define MPU3050_PWR_MGM_CLKSEL		0x07
+#define MPU3050_PWR_MGM_STBY_ZG	0x08
+#define MPU3050_PWR_MGM_STBY_YG	0x10
+#define MPU3050_PWR_MGM_STBY_XG	0x20
+#define MPU3050_PWR_MGM_SLEEP		0x40
+#define MPU3050_PWR_MGM_RESET		0x80
+#define MPU3050_PWR_MGM_MASK		0x40
+
 struct axis_data {
 struct axis_data {
 	s16 x;
 	s16 x;
 	s16 y;
 	s16 y;
@@ -148,9 +197,20 @@ static void mpu3050_set_power_mode(struct i2c_client *client, u8 val)
 static int mpu3050_input_open(struct input_dev *input)
 static int mpu3050_input_open(struct input_dev *input)
 {
 {
 	struct mpu3050_sensor *sensor = input_get_drvdata(input);
 	struct mpu3050_sensor *sensor = input_get_drvdata(input);
+	int error;
 
 
 	pm_runtime_get(sensor->dev);
 	pm_runtime_get(sensor->dev);
 
 
+	/* Enable interrupts */
+	error = i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
+					  MPU3050_LATCH_INT_EN |
+					  MPU3050_RAW_RDY_EN |
+					  MPU3050_MPU_RDY_EN);
+	if (error < 0) {
+		pm_runtime_put(sensor->dev);
+		return error;
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -191,6 +251,51 @@ static irqreturn_t mpu3050_interrupt_thread(int irq, void *data)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+/**
+ *	mpu3050_hw_init	-	initialize hardware
+ *	@sensor: the sensor
+ *
+ *	Called during device probe; configures the sampling method.
+ */
+static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor)
+{
+	struct i2c_client *client = sensor->client;
+	int ret;
+	u8 reg;
+
+	/* Reset */
+	ret = i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM,
+					MPU3050_PWR_MGM_RESET);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM);
+	if (ret < 0)
+		return ret;
+
+	ret &= ~MPU3050_PWR_MGM_CLKSEL;
+	ret |= MPU3050_PWR_MGM_PLL_Z;
+	ret = i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, ret);
+	if (ret < 0)
+		return ret;
+
+	/* Output frequency divider. The poll interval */
+	ret = i2c_smbus_write_byte_data(client, MPU3050_SMPLRT_DIV,
+					MPU3050_DEFAULT_POLL_INTERVAL - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Set low pass filter and full scale */
+	reg = MPU3050_DEFAULT_FS_RANGE;
+	reg |= MPU3050_DLPF_CFG_42HZ << 3;
+	reg |= MPU3050_EXT_SYNC_NONE << 5;
+	ret = i2c_smbus_write_byte_data(client, MPU3050_DLPF_FS_SYNC, reg);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 /**
 /**
  *	mpu3050_probe	-	device detection callback
  *	mpu3050_probe	-	device detection callback
  *	@client: i2c client of found device
  *	@client: i2c client of found device
@@ -256,10 +361,14 @@ static int __devinit mpu3050_probe(struct i2c_client *client,
 
 
 	pm_runtime_set_active(&client->dev);
 	pm_runtime_set_active(&client->dev);
 
 
+	error = mpu3050_hw_init(sensor);
+	if (error)
+		goto err_pm_set_suspended;
+
 	error = request_threaded_irq(client->irq,
 	error = request_threaded_irq(client->irq,
 				     NULL, mpu3050_interrupt_thread,
 				     NULL, mpu3050_interrupt_thread,
 				     IRQF_TRIGGER_RISING,
 				     IRQF_TRIGGER_RISING,
-				     "mpu_int", sensor);
+				     "mpu3050", sensor);
 	if (error) {
 	if (error) {
 		dev_err(&client->dev,
 		dev_err(&client->dev,
 			"can't get IRQ %d, error %d\n", client->irq, error);
 			"can't get IRQ %d, error %d\n", client->irq, error);
@@ -348,11 +457,18 @@ static const struct i2c_device_id mpu3050_ids[] = {
 };
 };
 MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
 MODULE_DEVICE_TABLE(i2c, mpu3050_ids);
 
 
+static const struct of_device_id mpu3050_of_match[] = {
+	{ .compatible = "invn,mpu3050", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mpu3050_of_match);
+
 static struct i2c_driver mpu3050_i2c_driver = {
 static struct i2c_driver mpu3050_i2c_driver = {
 	.driver	= {
 	.driver	= {
 		.name	= "mpu3050",
 		.name	= "mpu3050",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.pm	= &mpu3050_pm,
 		.pm	= &mpu3050_pm,
+		.of_match_table = mpu3050_of_match,
 	},
 	},
 	.probe		= mpu3050_probe,
 	.probe		= mpu3050_probe,
 	.remove		= __devexit_p(mpu3050_remove),
 	.remove		= __devexit_p(mpu3050_remove),

+ 1 - 13
drivers/input/misc/pcap_keys.c

@@ -125,19 +125,7 @@ static struct platform_driver pcap_keys_device_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	}
 	}
 };
 };
-
-static int __init pcap_keys_init(void)
-{
-	return platform_driver_register(&pcap_keys_device_driver);
-};
-
-static void __exit pcap_keys_exit(void)
-{
-	platform_driver_unregister(&pcap_keys_device_driver);
-};
-
-module_init(pcap_keys_init);
-module_exit(pcap_keys_exit);
+module_platform_driver(pcap_keys_device_driver);
 
 
 MODULE_DESCRIPTION("Motorola PCAP2 input events driver");
 MODULE_DESCRIPTION("Motorola PCAP2 input events driver");
 MODULE_AUTHOR("Ilya Petrov <ilya.muromec@gmail.com>");
 MODULE_AUTHOR("Ilya Petrov <ilya.muromec@gmail.com>");

+ 1 - 12
drivers/input/misc/pcf50633-input.c

@@ -113,18 +113,7 @@ static struct platform_driver pcf50633_input_driver = {
 	.probe = pcf50633_input_probe,
 	.probe = pcf50633_input_probe,
 	.remove = __devexit_p(pcf50633_input_remove),
 	.remove = __devexit_p(pcf50633_input_remove),
 };
 };
-
-static int __init pcf50633_input_init(void)
-{
-	return platform_driver_register(&pcf50633_input_driver);
-}
-module_init(pcf50633_input_init);
-
-static void __exit pcf50633_input_exit(void)
-{
-	platform_driver_unregister(&pcf50633_input_driver);
-}
-module_exit(pcf50633_input_exit);
+module_platform_driver(pcf50633_input_driver);
 
 
 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
 MODULE_DESCRIPTION("PCF50633 input driver");
 MODULE_DESCRIPTION("PCF50633 input driver");

+ 1 - 13
drivers/input/misc/pcspkr.c

@@ -134,17 +134,5 @@ static struct platform_driver pcspkr_platform_driver = {
 	.remove		= __devexit_p(pcspkr_remove),
 	.remove		= __devexit_p(pcspkr_remove),
 	.shutdown	= pcspkr_shutdown,
 	.shutdown	= pcspkr_shutdown,
 };
 };
+module_platform_driver(pcspkr_platform_driver);
 
 
-
-static int __init pcspkr_init(void)
-{
-	return platform_driver_register(&pcspkr_platform_driver);
-}
-
-static void __exit pcspkr_exit(void)
-{
-	platform_driver_unregister(&pcspkr_platform_driver);
-}
-
-module_init(pcspkr_init);
-module_exit(pcspkr_exit);

+ 1 - 12
drivers/input/misc/pm8xxx-vibrator.c

@@ -277,18 +277,7 @@ static struct platform_driver pm8xxx_vib_driver = {
 		.pm	= &pm8xxx_vib_pm_ops,
 		.pm	= &pm8xxx_vib_pm_ops,
 	},
 	},
 };
 };
-
-static int __init pm8xxx_vib_init(void)
-{
-	return platform_driver_register(&pm8xxx_vib_driver);
-}
-module_init(pm8xxx_vib_init);
-
-static void __exit pm8xxx_vib_exit(void)
-{
-	platform_driver_unregister(&pm8xxx_vib_driver);
-}
-module_exit(pm8xxx_vib_exit);
+module_platform_driver(pm8xxx_vib_driver);
 
 
 MODULE_ALIAS("platform:pm8xxx_vib");
 MODULE_ALIAS("platform:pm8xxx_vib");
 MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");
 MODULE_DESCRIPTION("PMIC8xxx vibrator driver based on ff-memless framework");

+ 1 - 12
drivers/input/misc/pmic8xxx-pwrkey.c

@@ -213,18 +213,7 @@ static struct platform_driver pmic8xxx_pwrkey_driver = {
 		.pm	= &pm8xxx_pwr_key_pm_ops,
 		.pm	= &pm8xxx_pwr_key_pm_ops,
 	},
 	},
 };
 };
-
-static int __init pmic8xxx_pwrkey_init(void)
-{
-	return platform_driver_register(&pmic8xxx_pwrkey_driver);
-}
-module_init(pmic8xxx_pwrkey_init);
-
-static void __exit pmic8xxx_pwrkey_exit(void)
-{
-	platform_driver_unregister(&pmic8xxx_pwrkey_driver);
-}
-module_exit(pmic8xxx_pwrkey_exit);
+module_platform_driver(pmic8xxx_pwrkey_driver);
 
 
 MODULE_ALIAS("platform:pmic8xxx_pwrkey");
 MODULE_ALIAS("platform:pmic8xxx_pwrkey");
 MODULE_DESCRIPTION("PMIC8XXX Power Key driver");
 MODULE_DESCRIPTION("PMIC8XXX Power Key driver");

+ 1 - 12
drivers/input/misc/pwm-beeper.c

@@ -180,18 +180,7 @@ static struct platform_driver pwm_beeper_driver = {
 		.pm	= PWM_BEEPER_PM_OPS,
 		.pm	= PWM_BEEPER_PM_OPS,
 	},
 	},
 };
 };
-
-static int __init pwm_beeper_init(void)
-{
-	return platform_driver_register(&pwm_beeper_driver);
-}
-module_init(pwm_beeper_init);
-
-static void __exit pwm_beeper_exit(void)
-{
-	platform_driver_unregister(&pwm_beeper_driver);
-}
-module_exit(pwm_beeper_exit);
+module_platform_driver(pwm_beeper_driver);
 
 
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("PWM beeper driver");
 MODULE_DESCRIPTION("PWM beeper driver");

+ 1 - 13
drivers/input/misc/rb532_button.c

@@ -100,19 +100,7 @@ static struct platform_driver rb532_button_driver = {
 		.owner = THIS_MODULE,
 		.owner = THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init rb532_button_init(void)
-{
-	return platform_driver_register(&rb532_button_driver);
-}
-
-static void __exit rb532_button_exit(void)
-{
-	platform_driver_unregister(&rb532_button_driver);
-}
-
-module_init(rb532_button_init);
-module_exit(rb532_button_exit);
+module_platform_driver(rb532_button_driver);
 
 
 MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
 MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 1 - 13
drivers/input/misc/rotary_encoder.c

@@ -284,19 +284,7 @@ static struct platform_driver rotary_encoder_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	}
 	}
 };
 };
-
-static int __init rotary_encoder_init(void)
-{
-	return platform_driver_register(&rotary_encoder_driver);
-}
-
-static void __exit rotary_encoder_exit(void)
-{
-	platform_driver_unregister(&rotary_encoder_driver);
-}
-
-module_init(rotary_encoder_init);
-module_exit(rotary_encoder_exit);
+module_platform_driver(rotary_encoder_driver);
 
 
 MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_DESCRIPTION("GPIO rotary encoder driver");
 MODULE_DESCRIPTION("GPIO rotary encoder driver");

+ 1 - 12
drivers/input/misc/sgi_btns.c

@@ -164,17 +164,6 @@ static struct platform_driver sgi_buttons_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init sgi_buttons_init(void)
-{
-	return platform_driver_register(&sgi_buttons_driver);
-}
-
-static void __exit sgi_buttons_exit(void)
-{
-	platform_driver_unregister(&sgi_buttons_driver);
-}
+module_platform_driver(sgi_buttons_driver);
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-module_init(sgi_buttons_init);
-module_exit(sgi_buttons_exit);

+ 2 - 13
drivers/input/misc/twl4030-pwrbutton.c

@@ -107,25 +107,14 @@ static int __exit twl4030_pwrbutton_remove(struct platform_device *pdev)
 }
 }
 
 
 static struct platform_driver twl4030_pwrbutton_driver = {
 static struct platform_driver twl4030_pwrbutton_driver = {
+	.probe		= twl4030_pwrbutton_probe,
 	.remove		= __exit_p(twl4030_pwrbutton_remove),
 	.remove		= __exit_p(twl4030_pwrbutton_remove),
 	.driver		= {
 	.driver		= {
 		.name	= "twl4030_pwrbutton",
 		.name	= "twl4030_pwrbutton",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init twl4030_pwrbutton_init(void)
-{
-	return platform_driver_probe(&twl4030_pwrbutton_driver,
-			twl4030_pwrbutton_probe);
-}
-module_init(twl4030_pwrbutton_init);
-
-static void __exit twl4030_pwrbutton_exit(void)
-{
-	platform_driver_unregister(&twl4030_pwrbutton_driver);
-}
-module_exit(twl4030_pwrbutton_exit);
+module_platform_driver(twl4030_pwrbutton_driver);
 
 
 MODULE_ALIAS("platform:twl4030_pwrbutton");
 MODULE_ALIAS("platform:twl4030_pwrbutton");
 MODULE_DESCRIPTION("Triton2 Power Button");
 MODULE_DESCRIPTION("Triton2 Power Button");

+ 1 - 13
drivers/input/misc/twl4030-vibra.c

@@ -278,21 +278,9 @@ static struct platform_driver twl4030_vibra_driver = {
 #endif
 #endif
 	},
 	},
 };
 };
-
-static int __init twl4030_vibra_init(void)
-{
-	return platform_driver_register(&twl4030_vibra_driver);
-}
-module_init(twl4030_vibra_init);
-
-static void __exit twl4030_vibra_exit(void)
-{
-	platform_driver_unregister(&twl4030_vibra_driver);
-}
-module_exit(twl4030_vibra_exit);
+module_platform_driver(twl4030_vibra_driver);
 
 
 MODULE_ALIAS("platform:twl4030-vibra");
 MODULE_ALIAS("platform:twl4030-vibra");
-
 MODULE_DESCRIPTION("TWL4030 Vibra driver");
 MODULE_DESCRIPTION("TWL4030 Vibra driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_AUTHOR("Nokia Corporation");

+ 1 - 12
drivers/input/misc/twl6040-vibra.c

@@ -410,18 +410,7 @@ static struct platform_driver twl6040_vibra_driver = {
 		.pm	= &twl6040_vibra_pm_ops,
 		.pm	= &twl6040_vibra_pm_ops,
 	},
 	},
 };
 };
-
-static int __init twl6040_vibra_init(void)
-{
-	return platform_driver_register(&twl6040_vibra_driver);
-}
-module_init(twl6040_vibra_init);
-
-static void __exit twl6040_vibra_exit(void)
-{
-	platform_driver_unregister(&twl6040_vibra_driver);
-}
-module_exit(twl6040_vibra_exit);
+module_platform_driver(twl6040_vibra_driver);
 
 
 MODULE_ALIAS("platform:twl6040-vibra");
 MODULE_ALIAS("platform:twl6040-vibra");
 MODULE_DESCRIPTION("TWL6040 Vibra driver");
 MODULE_DESCRIPTION("TWL6040 Vibra driver");

+ 1 - 12
drivers/input/misc/wm831x-on.c

@@ -145,18 +145,7 @@ static struct platform_driver wm831x_on_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init wm831x_on_init(void)
-{
-	return platform_driver_register(&wm831x_on_driver);
-}
-module_init(wm831x_on_init);
-
-static void __exit wm831x_on_exit(void)
-{
-	platform_driver_unregister(&wm831x_on_driver);
-}
-module_exit(wm831x_on_exit);
+module_platform_driver(wm831x_on_driver);
 
 
 MODULE_ALIAS("platform:wm831x-on");
 MODULE_ALIAS("platform:wm831x-on");
 MODULE_DESCRIPTION("WM831x ON pin");
 MODULE_DESCRIPTION("WM831x ON pin");

File diff suppressed because it is too large
+ 929 - 78
drivers/input/mouse/alps.c


+ 19 - 0
drivers/input/mouse/alps.h

@@ -12,20 +12,39 @@
 #ifndef _ALPS_H
 #ifndef _ALPS_H
 #define _ALPS_H
 #define _ALPS_H
 
 
+#define ALPS_PROTO_V1	0
+#define ALPS_PROTO_V2	1
+#define ALPS_PROTO_V3	2
+#define ALPS_PROTO_V4	3
+
 struct alps_model_info {
 struct alps_model_info {
         unsigned char signature[3];
         unsigned char signature[3];
+	unsigned char command_mode_resp; /* v3/v4 only */
+	unsigned char proto_version;
         unsigned char byte0, mask0;
         unsigned char byte0, mask0;
         unsigned char flags;
         unsigned char flags;
 };
 };
 
 
+struct alps_nibble_commands {
+	int command;
+	unsigned char data;
+};
+
 struct alps_data {
 struct alps_data {
 	struct input_dev *dev2;		/* Relative device */
 	struct input_dev *dev2;		/* Relative device */
 	char phys[32];			/* Phys */
 	char phys[32];			/* Phys */
 	const struct alps_model_info *i;/* Info */
 	const struct alps_model_info *i;/* Info */
+	const struct alps_nibble_commands *nibble_commands;
+	int addr_command;		/* Command to set register address */
 	int prev_fin;			/* Finger bit from previous packet */
 	int prev_fin;			/* Finger bit from previous packet */
+	int multi_packet;		/* Multi-packet data in progress */
+	unsigned char multi_data[6];	/* Saved multi-packet data */
+	u8 quirks;
 	struct timer_list timer;
 	struct timer_list timer;
 };
 };
 
 
+#define ALPS_QUIRK_TRACKSTICK_BUTTONS	1 /* trakcstick buttons in trackstick packet */
+
 #ifdef CONFIG_MOUSE_PS2_ALPS
 #ifdef CONFIG_MOUSE_PS2_ALPS
 int alps_detect(struct psmouse *psmouse, bool set_properties);
 int alps_detect(struct psmouse *psmouse, bool set_properties);
 int alps_init(struct psmouse *psmouse);
 int alps_init(struct psmouse *psmouse);

+ 2 - 14
drivers/input/mouse/amimouse.c

@@ -140,25 +140,13 @@ static int __exit amimouse_remove(struct platform_device *pdev)
 }
 }
 
 
 static struct platform_driver amimouse_driver = {
 static struct platform_driver amimouse_driver = {
+	.probe = amimouse_probe,
 	.remove = __exit_p(amimouse_remove),
 	.remove = __exit_p(amimouse_remove),
 	.driver   = {
 	.driver   = {
 		.name	= "amiga-mouse",
 		.name	= "amiga-mouse",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init amimouse_init(void)
-{
-	return platform_driver_probe(&amimouse_driver, amimouse_probe);
-}
-
-module_init(amimouse_init);
-
-static void __exit amimouse_exit(void)
-{
-	platform_driver_unregister(&amimouse_driver);
-}
-
-module_exit(amimouse_exit);
+module_platform_driver(amimouse_driver);
 
 
 MODULE_ALIAS("platform:amiga-mouse");
 MODULE_ALIAS("platform:amiga-mouse");

+ 67 - 13
drivers/input/mouse/elantech.c

@@ -42,6 +42,24 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * V3 and later support this fast command
+ */
+static int elantech_send_cmd(struct psmouse *psmouse, unsigned char c,
+				unsigned char *param)
+{
+	struct ps2dev *ps2dev = &psmouse->ps2dev;
+
+	if (ps2_command(ps2dev, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    ps2_command(ps2dev, NULL, c) ||
+	    ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) {
+		psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
 /*
  * A retrying version of ps2_command
  * A retrying version of ps2_command
  */
  */
@@ -863,13 +881,13 @@ static int elantech_set_range(struct psmouse *psmouse,
 			i = (etd->fw_version > 0x020800 &&
 			i = (etd->fw_version > 0x020800 &&
 			     etd->fw_version < 0x020900) ? 1 : 2;
 			     etd->fw_version < 0x020900) ? 1 : 2;
 
 
-			if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+			if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
 				return -1;
 				return -1;
 
 
 			fixed_dpi = param[1] & 0x10;
 			fixed_dpi = param[1] & 0x10;
 
 
 			if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
 			if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
-				if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+				if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
 					return -1;
 					return -1;
 
 
 				*x_max = (etd->capabilities[1] - i) * param[1] / 2;
 				*x_max = (etd->capabilities[1] - i) * param[1] / 2;
@@ -888,7 +906,7 @@ static int elantech_set_range(struct psmouse *psmouse,
 		break;
 		break;
 
 
 	case 3:
 	case 3:
-		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+		if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
 			return -1;
 			return -1;
 
 
 		*x_max = (0x0f & param[0]) << 8 | param[1];
 		*x_max = (0x0f & param[0]) << 8 | param[1];
@@ -896,7 +914,7 @@ static int elantech_set_range(struct psmouse *psmouse,
 		break;
 		break;
 
 
 	case 4:
 	case 4:
-		if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+		if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
 			return -1;
 			return -1;
 
 
 		*x_max = (0x0f & param[0]) << 8 | param[1];
 		*x_max = (0x0f & param[0]) << 8 | param[1];
@@ -912,6 +930,30 @@ static int elantech_set_range(struct psmouse *psmouse,
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * (value from firmware) * 10 + 790 = dpi
+ * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
+ */
+static unsigned int elantech_convert_res(unsigned int val)
+{
+	return (val * 10 + 790) * 10 / 254;
+}
+
+static int elantech_get_resolution_v4(struct psmouse *psmouse,
+				      unsigned int *x_res,
+				      unsigned int *y_res)
+{
+	unsigned char param[3];
+
+	if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param))
+		return -1;
+
+	*x_res = elantech_convert_res(param[1] & 0x0f);
+	*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+
+	return 0;
+}
+
 /*
 /*
  * Set the appropriate event bits for the input subsystem
  * Set the appropriate event bits for the input subsystem
  */
  */
@@ -920,6 +962,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
 	struct elantech_data *etd = psmouse->private;
 	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
 	unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
+	unsigned int x_res = 0, y_res = 0;
 
 
 	if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
 	if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
 		return -1;
 		return -1;
@@ -967,10 +1010,20 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 		break;
 		break;
 
 
 	case 4:
 	case 4:
+		if (elantech_get_resolution_v4(psmouse, &x_res, &y_res)) {
+			/*
+			 * if query failed, print a warning and leave the values
+			 * zero to resemble synaptics.c behavior.
+			 */
+			psmouse_warn(psmouse, "couldn't query resolution data.\n");
+		}
+
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
 		__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
 		/* For X to recognize me as touchpad. */
 		/* For X to recognize me as touchpad. */
 		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
 		input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
+		input_abs_set_res(dev, ABS_X, x_res);
+		input_abs_set_res(dev, ABS_Y, y_res);
 		/*
 		/*
 		 * range of pressure and width is the same as v2,
 		 * range of pressure and width is the same as v2,
 		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
 		 * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
@@ -983,6 +1036,8 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 		input_mt_init_slots(dev, ETP_MAX_FINGERS);
 		input_mt_init_slots(dev, ETP_MAX_FINGERS);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+		input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
+		input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
 		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
 		input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
 				     ETP_PMAX_V2, 0, 0);
 				     ETP_PMAX_V2, 0, 0);
 		/*
 		/*
@@ -1031,16 +1086,13 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse,
 	struct elantech_data *etd = psmouse->private;
 	struct elantech_data *etd = psmouse->private;
 	struct elantech_attr_data *attr = data;
 	struct elantech_attr_data *attr = data;
 	unsigned char *reg = (unsigned char *) etd + attr->field_offset;
 	unsigned char *reg = (unsigned char *) etd + attr->field_offset;
-	unsigned long value;
+	unsigned char value;
 	int err;
 	int err;
 
 
-	err = strict_strtoul(buf, 16, &value);
+	err = kstrtou8(buf, 16, &value);
 	if (err)
 	if (err)
 		return err;
 		return err;
 
 
-	if (value > 0xff)
-		return -EINVAL;
-
 	/* Do we need to preserve some bits for version 2 hardware too? */
 	/* Do we need to preserve some bits for version 2 hardware too? */
 	if (etd->hw_version == 1) {
 	if (etd->hw_version == 1) {
 		if (attr->reg == 0x10)
 		if (attr->reg == 0x10)
@@ -1233,9 +1285,11 @@ static int elantech_set_properties(struct elantech_data *etd)
 		}
 		}
 	}
 	}
 
 
-	/*
-	 * Turn on packet checking by default.
-	 */
+	/* decide which send_cmd we're gonna use early */
+	etd->send_cmd = etd->hw_version >= 3 ? elantech_send_cmd :
+					       synaptics_send_cmd;
+
+	/* Turn on packet checking by default */
 	etd->paritycheck = 1;
 	etd->paritycheck = 1;
 
 
 	/*
 	/*
@@ -1291,7 +1345,7 @@ int elantech_init(struct psmouse *psmouse)
 		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
 		     "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n",
 		     etd->hw_version, param[0], param[1], param[2]);
 		     etd->hw_version, param[0], param[1], param[2]);
 
 
-	if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
+	if (etd->send_cmd(psmouse, ETP_CAPABILITIES_QUERY,
 	    etd->capabilities)) {
 	    etd->capabilities)) {
 		psmouse_err(psmouse, "failed to query capabilities.\n");
 		psmouse_err(psmouse, "failed to query capabilities.\n");
 		goto init_fail;
 		goto init_fail;

+ 2 - 0
drivers/input/mouse/elantech.h

@@ -20,6 +20,7 @@
 #define ETP_FW_VERSION_QUERY		0x01
 #define ETP_FW_VERSION_QUERY		0x01
 #define ETP_CAPABILITIES_QUERY		0x02
 #define ETP_CAPABILITIES_QUERY		0x02
 #define ETP_SAMPLE_QUERY		0x03
 #define ETP_SAMPLE_QUERY		0x03
+#define ETP_RESOLUTION_QUERY		0x04
 
 
 /*
 /*
  * Command values for register reading or writing
  * Command values for register reading or writing
@@ -135,6 +136,7 @@ struct elantech_data {
 	unsigned int width;
 	unsigned int width;
 	struct finger_pos mt[ETP_MAX_FINGERS];
 	struct finger_pos mt[ETP_MAX_FINGERS];
 	unsigned char parity[256];
 	unsigned char parity[256];
+	int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param);
 };
 };
 
 
 #ifdef CONFIG_MOUSE_PS2_ELANTECH
 #ifdef CONFIG_MOUSE_PS2_ELANTECH

+ 1 - 12
drivers/input/mouse/gpio_mouse.c

@@ -178,18 +178,7 @@ static struct platform_driver gpio_mouse_device_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	}
 	}
 };
 };
-
-static int __init gpio_mouse_init(void)
-{
-	return platform_driver_register(&gpio_mouse_device_driver);
-}
-module_init(gpio_mouse_init);
-
-static void __exit gpio_mouse_exit(void)
-{
-	platform_driver_unregister(&gpio_mouse_device_driver);
-}
-module_exit(gpio_mouse_exit);
+module_platform_driver(gpio_mouse_device_driver);
 
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_DESCRIPTION("GPIO mouse driver");

+ 12 - 6
drivers/input/mouse/hgpk.c

@@ -789,11 +789,14 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data,
 				const char *buf, size_t count)
 				const char *buf, size_t count)
 {
 {
 	struct hgpk_data *priv = psmouse->private;
 	struct hgpk_data *priv = psmouse->private;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 
 
-	err = strict_strtoul(buf, 10, &value);
-	if (err || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (value != priv->powered) {
 	if (value != priv->powered) {
@@ -881,11 +884,14 @@ static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data,
 				const char *buf, size_t count)
 				const char *buf, size_t count)
 {
 {
 	struct hgpk_data *priv = psmouse->private;
 	struct hgpk_data *priv = psmouse->private;
-	unsigned long value;
+	unsigned int value;
 	int err;
 	int err;
 
 
-	err = strict_strtoul(buf, 10, &value);
-	if (err || value != 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value != 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/*
 	/*

+ 7 - 2
drivers/input/mouse/logips2pp.c

@@ -155,9 +155,14 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse,
 static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data,
 static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data,
 					  const char *buf, size_t count)
 					  const char *buf, size_t count)
 {
 {
-	unsigned long value;
+	unsigned int value;
+	int err;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	ps2pp_set_smartscroll(psmouse, value);
 	ps2pp_set_smartscroll(psmouse, value);

+ 147 - 82
drivers/input/mouse/psmouse-base.c

@@ -127,7 +127,7 @@ struct psmouse_protocol {
  * relevant events to the input module once full packet has arrived.
  * relevant events to the input module once full packet has arrived.
  */
  */
 
 
-static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
+psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
 {
 {
 	struct input_dev *dev = psmouse->dev;
 	struct input_dev *dev = psmouse->dev;
 	unsigned char *packet = psmouse->packet;
 	unsigned char *packet = psmouse->packet;
@@ -418,6 +418,49 @@ int psmouse_reset(struct psmouse *psmouse)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * Here we set the mouse resolution.
+ */
+
+void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution)
+{
+	static const unsigned char params[] = { 0, 1, 2, 2, 3 };
+	unsigned char p;
+
+	if (resolution == 0 || resolution > 200)
+		resolution = 200;
+
+	p = params[resolution / 50];
+	ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES);
+	psmouse->resolution = 25 << p;
+}
+
+/*
+ * Here we set the mouse report rate.
+ */
+
+static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
+{
+	static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
+	unsigned char r;
+	int i = 0;
+
+	while (rates[i] > rate) i++;
+	r = rates[i];
+	ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE);
+	psmouse->rate = r;
+}
+
+/*
+ * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
+ */
+
+static int psmouse_poll(struct psmouse *psmouse)
+{
+	return ps2_command(&psmouse->ps2dev, psmouse->packet,
+			   PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
+}
+
 
 
 /*
 /*
  * Genius NetMouse magic init.
  * Genius NetMouse magic init.
@@ -602,6 +645,56 @@ static int cortron_detect(struct psmouse *psmouse, bool set_properties)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * Apply default settings to the psmouse structure. Most of them will
+ * be overridden by individual protocol initialization routines.
+ */
+
+static void psmouse_apply_defaults(struct psmouse *psmouse)
+{
+	struct input_dev *input_dev = psmouse->dev;
+
+	memset(input_dev->evbit, 0, sizeof(input_dev->evbit));
+	memset(input_dev->keybit, 0, sizeof(input_dev->keybit));
+	memset(input_dev->relbit, 0, sizeof(input_dev->relbit));
+	memset(input_dev->absbit, 0, sizeof(input_dev->absbit));
+	memset(input_dev->mscbit, 0, sizeof(input_dev->mscbit));
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_REL, input_dev->evbit);
+
+	__set_bit(BTN_LEFT, input_dev->keybit);
+	__set_bit(BTN_RIGHT, input_dev->keybit);
+
+	__set_bit(REL_X, input_dev->relbit);
+	__set_bit(REL_Y, input_dev->relbit);
+
+	psmouse->set_rate = psmouse_set_rate;
+	psmouse->set_resolution = psmouse_set_resolution;
+	psmouse->poll = psmouse_poll;
+	psmouse->protocol_handler = psmouse_process_byte;
+	psmouse->pktsize = 3;
+	psmouse->reconnect = NULL;
+	psmouse->disconnect = NULL;
+	psmouse->cleanup = NULL;
+	psmouse->pt_activate = NULL;
+	psmouse->pt_deactivate = NULL;
+}
+
+/*
+ * Apply default settings to the psmouse structure and call specified
+ * protocol detection or initialization routine.
+ */
+static int psmouse_do_detect(int (*detect)(struct psmouse *psmouse,
+					   bool set_properties),
+			     struct psmouse *psmouse, bool set_properties)
+{
+	if (set_properties)
+		psmouse_apply_defaults(psmouse);
+
+	return detect(psmouse, set_properties);
+}
+
 /*
 /*
  * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
  * psmouse_extensions() probes for any extensions to the basic PS/2 protocol
  * the mouse may have.
  * the mouse may have.
@@ -616,7 +709,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
  * We always check for lifebook because it does not disturb mouse
  * We always check for lifebook because it does not disturb mouse
  * (it only checks DMI information).
  * (it only checks DMI information).
  */
  */
-	if (lifebook_detect(psmouse, set_properties) == 0) {
+	if (psmouse_do_detect(lifebook_detect, psmouse, set_properties) == 0) {
 		if (max_proto > PSMOUSE_IMEX) {
 		if (max_proto > PSMOUSE_IMEX) {
 			if (!set_properties || lifebook_init(psmouse) == 0)
 			if (!set_properties || lifebook_init(psmouse) == 0)
 				return PSMOUSE_LIFEBOOK;
 				return PSMOUSE_LIFEBOOK;
@@ -628,15 +721,18 @@ static int psmouse_extensions(struct psmouse *psmouse,
  * upsets the thinkingmouse).
  * upsets the thinkingmouse).
  */
  */
 
 
-	if (max_proto > PSMOUSE_IMEX && thinking_detect(psmouse, set_properties) == 0)
+	if (max_proto > PSMOUSE_IMEX &&
+	    psmouse_do_detect(thinking_detect, psmouse, set_properties) == 0) {
 		return PSMOUSE_THINKPS;
 		return PSMOUSE_THINKPS;
+	}
 
 
 /*
 /*
  * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol
  * Try Synaptics TouchPad. Note that probing is done even if Synaptics protocol
  * support is disabled in config - we need to know if it is synaptics so we
  * support is disabled in config - we need to know if it is synaptics so we
  * can reset it properly after probing for intellimouse.
  * can reset it properly after probing for intellimouse.
  */
  */
-	if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) {
+	if (max_proto > PSMOUSE_PS2 &&
+	    psmouse_do_detect(synaptics_detect, psmouse, set_properties) == 0) {
 		synaptics_hardware = true;
 		synaptics_hardware = true;
 
 
 		if (max_proto > PSMOUSE_IMEX) {
 		if (max_proto > PSMOUSE_IMEX) {
@@ -667,7 +763,8 @@ static int psmouse_extensions(struct psmouse *psmouse,
  */
  */
 	if (max_proto > PSMOUSE_IMEX) {
 	if (max_proto > PSMOUSE_IMEX) {
 		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 		ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
-		if (alps_detect(psmouse, set_properties) == 0) {
+		if (psmouse_do_detect(alps_detect,
+				      psmouse, set_properties) == 0) {
 			if (!set_properties || alps_init(psmouse) == 0)
 			if (!set_properties || alps_init(psmouse) == 0)
 				return PSMOUSE_ALPS;
 				return PSMOUSE_ALPS;
 /*
 /*
@@ -681,7 +778,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
  * Try OLPC HGPK touchpad.
  * Try OLPC HGPK touchpad.
  */
  */
 	if (max_proto > PSMOUSE_IMEX &&
 	if (max_proto > PSMOUSE_IMEX &&
-			hgpk_detect(psmouse, set_properties) == 0) {
+	    psmouse_do_detect(hgpk_detect, psmouse, set_properties) == 0) {
 		if (!set_properties || hgpk_init(psmouse) == 0)
 		if (!set_properties || hgpk_init(psmouse) == 0)
 			return PSMOUSE_HGPK;
 			return PSMOUSE_HGPK;
 /*
 /*
@@ -694,7 +791,7 @@ static int psmouse_extensions(struct psmouse *psmouse,
  * Try Elantech touchpad.
  * Try Elantech touchpad.
  */
  */
 	if (max_proto > PSMOUSE_IMEX &&
 	if (max_proto > PSMOUSE_IMEX &&
-			elantech_detect(psmouse, set_properties) == 0) {
+	    psmouse_do_detect(elantech_detect, psmouse, set_properties) == 0) {
 		if (!set_properties || elantech_init(psmouse) == 0)
 		if (!set_properties || elantech_init(psmouse) == 0)
 			return PSMOUSE_ELANTECH;
 			return PSMOUSE_ELANTECH;
 /*
 /*
@@ -703,18 +800,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
 		max_proto = PSMOUSE_IMEX;
 		max_proto = PSMOUSE_IMEX;
 	}
 	}
 
 
-
 	if (max_proto > PSMOUSE_IMEX) {
 	if (max_proto > PSMOUSE_IMEX) {
-		if (genius_detect(psmouse, set_properties) == 0)
+		if (psmouse_do_detect(genius_detect,
+				      psmouse, set_properties) == 0)
 			return PSMOUSE_GENPS;
 			return PSMOUSE_GENPS;
 
 
-		if (ps2pp_init(psmouse, set_properties) == 0)
+		if (psmouse_do_detect(ps2pp_init,
+				      psmouse, set_properties) == 0)
 			return PSMOUSE_PS2PP;
 			return PSMOUSE_PS2PP;
 
 
-		if (trackpoint_detect(psmouse, set_properties) == 0)
+		if (psmouse_do_detect(trackpoint_detect,
+				      psmouse, set_properties) == 0)
 			return PSMOUSE_TRACKPOINT;
 			return PSMOUSE_TRACKPOINT;
 
 
-		if (touchkit_ps2_detect(psmouse, set_properties) == 0)
+		if (psmouse_do_detect(touchkit_ps2_detect,
+				      psmouse, set_properties) == 0)
 			return PSMOUSE_TOUCHKIT_PS2;
 			return PSMOUSE_TOUCHKIT_PS2;
 	}
 	}
 
 
@@ -723,7 +823,8 @@ static int psmouse_extensions(struct psmouse *psmouse,
  * Trackpoint devices (causing TP_READ_ID command to time out).
  * Trackpoint devices (causing TP_READ_ID command to time out).
  */
  */
 	if (max_proto > PSMOUSE_IMEX) {
 	if (max_proto > PSMOUSE_IMEX) {
-		if (fsp_detect(psmouse, set_properties) == 0) {
+		if (psmouse_do_detect(fsp_detect,
+				      psmouse, set_properties) == 0) {
 			if (!set_properties || fsp_init(psmouse) == 0)
 			if (!set_properties || fsp_init(psmouse) == 0)
 				return PSMOUSE_FSP;
 				return PSMOUSE_FSP;
 /*
 /*
@@ -741,17 +842,23 @@ static int psmouse_extensions(struct psmouse *psmouse,
 	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 	ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
 	psmouse_reset(psmouse);
 	psmouse_reset(psmouse);
 
 
-	if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
+	if (max_proto >= PSMOUSE_IMEX &&
+	    psmouse_do_detect(im_explorer_detect,
+			      psmouse, set_properties) == 0) {
 		return PSMOUSE_IMEX;
 		return PSMOUSE_IMEX;
+	}
 
 
-	if (max_proto >= PSMOUSE_IMPS && intellimouse_detect(psmouse, set_properties) == 0)
+	if (max_proto >= PSMOUSE_IMPS &&
+	    psmouse_do_detect(intellimouse_detect,
+			      psmouse, set_properties) == 0) {
 		return PSMOUSE_IMPS;
 		return PSMOUSE_IMPS;
+	}
 
 
 /*
 /*
  * Okay, all failed, we have a standard mouse here. The number of the buttons
  * Okay, all failed, we have a standard mouse here. The number of the buttons
  * is still a question, though. We assume 3.
  * is still a question, though. We assume 3.
  */
  */
-	ps2bare_detect(psmouse, set_properties);
+	psmouse_do_detect(ps2bare_detect, psmouse, set_properties);
 
 
 	if (synaptics_hardware) {
 	if (synaptics_hardware) {
 /*
 /*
@@ -819,6 +926,13 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.detect		= synaptics_detect,
 		.detect		= synaptics_detect,
 		.init		= synaptics_init,
 		.init		= synaptics_init,
 	},
 	},
+	{
+		.type		= PSMOUSE_SYNAPTICS_RELATIVE,
+		.name		= "SynRelPS/2",
+		.alias		= "synaptics-relative",
+		.detect		= synaptics_detect,
+		.init		= synaptics_init_relative,
+	},
 #endif
 #endif
 #ifdef CONFIG_MOUSE_PS2_ALPS
 #ifdef CONFIG_MOUSE_PS2_ALPS
 	{
 	{
@@ -957,39 +1071,6 @@ static int psmouse_probe(struct psmouse *psmouse)
 	return 0;
 	return 0;
 }
 }
 
 
-/*
- * Here we set the mouse resolution.
- */
-
-void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution)
-{
-	static const unsigned char params[] = { 0, 1, 2, 2, 3 };
-	unsigned char p;
-
-	if (resolution == 0 || resolution > 200)
-		resolution = 200;
-
-	p = params[resolution / 50];
-	ps2_command(&psmouse->ps2dev, &p, PSMOUSE_CMD_SETRES);
-	psmouse->resolution = 25 << p;
-}
-
-/*
- * Here we set the mouse report rate.
- */
-
-static void psmouse_set_rate(struct psmouse *psmouse, unsigned int rate)
-{
-	static const unsigned char rates[] = { 200, 100, 80, 60, 40, 20, 10, 0 };
-	unsigned char r;
-	int i = 0;
-
-	while (rates[i] > rate) i++;
-	r = rates[i];
-	ps2_command(&psmouse->ps2dev, &r, PSMOUSE_CMD_SETRATE);
-	psmouse->rate = r;
-}
-
 /*
 /*
  * psmouse_initialize() initializes the mouse to a sane state.
  * psmouse_initialize() initializes the mouse to a sane state.
  */
  */
@@ -1035,16 +1116,6 @@ static void psmouse_deactivate(struct psmouse *psmouse)
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 }
 }
 
 
-/*
- * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
- */
-
-static int psmouse_poll(struct psmouse *psmouse)
-{
-	return ps2_command(&psmouse->ps2dev, psmouse->packet,
-			   PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
-}
-
 
 
 /*
 /*
  * psmouse_resync() attempts to re-validate current protocol.
  * psmouse_resync() attempts to re-validate current protocol.
@@ -1245,18 +1316,9 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
 
 
 	input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 	input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
 
 
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
-	input_dev->keybit[BIT_WORD(BTN_MOUSE)] =
-				BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
-	input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
-
-	psmouse->set_rate = psmouse_set_rate;
-	psmouse->set_resolution = psmouse_set_resolution;
-	psmouse->poll = psmouse_poll;
-	psmouse->protocol_handler = psmouse_process_byte;
-	psmouse->pktsize = 3;
-
 	if (proto && (proto->detect || proto->init)) {
 	if (proto && (proto->detect || proto->init)) {
+		psmouse_apply_defaults(psmouse);
+
 		if (proto->detect && proto->detect(psmouse, true) < 0)
 		if (proto->detect && proto->detect(psmouse, true) < 0)
 			return -1;
 			return -1;
 
 
@@ -1558,13 +1620,12 @@ static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char
 static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
 static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count)
 {
 {
 	unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
 	unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset);
-	unsigned long value;
-
-	if (strict_strtoul(buf, 10, &value))
-		return -EINVAL;
+	unsigned int value;
+	int err;
 
 
-	if ((unsigned int)value != value)
-		return -EINVAL;
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
 
 
 	*field = value;
 	*field = value;
 
 
@@ -1671,10 +1732,12 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
 
 
 static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
 {
-	unsigned long value;
+	unsigned int value;
+	int err;
 
 
-	if (strict_strtoul(buf, 10, &value))
-		return -EINVAL;
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
 
 
 	psmouse->set_rate(psmouse, value);
 	psmouse->set_rate(psmouse, value);
 	return count;
 	return count;
@@ -1682,10 +1745,12 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const
 
 
 static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 static ssize_t psmouse_attr_set_resolution(struct psmouse *psmouse, void *data, const char *buf, size_t count)
 {
 {
-	unsigned long value;
+	unsigned int value;
+	int err;
 
 
-	if (strict_strtoul(buf, 10, &value))
-		return -EINVAL;
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
 
 
 	psmouse->set_resolution(psmouse, value);
 	psmouse->set_resolution(psmouse, value);
 	return count;
 	return count;

+ 3 - 0
drivers/input/mouse/psmouse.h

@@ -8,6 +8,7 @@
 #define PSMOUSE_CMD_SETSTREAM	0x00ea
 #define PSMOUSE_CMD_SETSTREAM	0x00ea
 #define PSMOUSE_CMD_SETPOLL	0x00f0
 #define PSMOUSE_CMD_SETPOLL	0x00f0
 #define PSMOUSE_CMD_POLL	0x00eb	/* caller sets number of bytes to receive */
 #define PSMOUSE_CMD_POLL	0x00eb	/* caller sets number of bytes to receive */
+#define PSMOUSE_CMD_RESET_WRAP	0x00ec
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_ENABLE	0x00f4
 #define PSMOUSE_CMD_ENABLE	0x00f4
@@ -93,6 +94,7 @@ enum psmouse_type {
 	PSMOUSE_HGPK,
 	PSMOUSE_HGPK,
 	PSMOUSE_ELANTECH,
 	PSMOUSE_ELANTECH,
 	PSMOUSE_FSP,
 	PSMOUSE_FSP,
+	PSMOUSE_SYNAPTICS_RELATIVE,
 	PSMOUSE_AUTO		/* This one should always be last */
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 };
 
 
@@ -102,6 +104,7 @@ int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
 int psmouse_reset(struct psmouse *psmouse);
 int psmouse_reset(struct psmouse *psmouse);
 void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
 void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state);
 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
+psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse);
 
 
 struct psmouse_attribute {
 struct psmouse_attribute {
 	struct device_attribute dattr;
 	struct device_attribute dattr;

+ 1 - 13
drivers/input/mouse/pxa930_trkball.c

@@ -250,19 +250,7 @@ static struct platform_driver pxa930_trkball_driver = {
 	.probe		= pxa930_trkball_probe,
 	.probe		= pxa930_trkball_probe,
 	.remove		= __devexit_p(pxa930_trkball_remove),
 	.remove		= __devexit_p(pxa930_trkball_remove),
 };
 };
-
-static int __init pxa930_trkball_init(void)
-{
-	return platform_driver_register(&pxa930_trkball_driver);
-}
-
-static void __exit pxa930_trkball_exit(void)
-{
-	platform_driver_unregister(&pxa930_trkball_driver);
-}
-
-module_init(pxa930_trkball_init);
-module_exit(pxa930_trkball_exit);
+module_platform_driver(pxa930_trkball_driver);
 
 
 MODULE_AUTHOR("Yong Yao <yaoyong@marvell.com>");
 MODULE_AUTHOR("Yong Yao <yaoyong@marvell.com>");
 MODULE_DESCRIPTION("PXA930 Trackball Mouse Driver");
 MODULE_DESCRIPTION("PXA930 Trackball Mouse Driver");

+ 32 - 11
drivers/input/mouse/sentelic.c

@@ -408,7 +408,7 @@ static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable)
 static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
 static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
 				   const char *buf, size_t count)
 				   const char *buf, size_t count)
 {
 {
-	unsigned long reg, val;
+	int reg, val;
 	char *rest;
 	char *rest;
 	ssize_t retval;
 	ssize_t retval;
 
 
@@ -416,7 +416,11 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data,
 	if (rest == buf || *rest != ' ' || reg > 0xff)
 	if (rest == buf || *rest != ' ' || reg > 0xff)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (strict_strtoul(rest + 1, 16, &val) || val > 0xff)
+	retval = kstrtoint(rest + 1, 16, &val);
+	if (retval)
+		return retval;
+
+	if (val > 0xff)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (fsp_reg_write_enable(psmouse, true))
 	if (fsp_reg_write_enable(psmouse, true))
@@ -448,10 +452,13 @@ static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data,
 					const char *buf, size_t count)
 					const char *buf, size_t count)
 {
 {
 	struct fsp_data *pad = psmouse->private;
 	struct fsp_data *pad = psmouse->private;
-	unsigned long reg;
-	int val;
+	int reg, val, err;
+
+	err = kstrtoint(buf, 16, &reg);
+	if (err)
+		return err;
 
 
-	if (strict_strtoul(buf, 16, &reg) || reg > 0xff)
+	if (reg > 0xff)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (fsp_reg_read(psmouse, reg, &val))
 	if (fsp_reg_read(psmouse, reg, &val))
@@ -480,9 +487,13 @@ static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse,
 static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
 static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data,
 					const char *buf, size_t count)
 					const char *buf, size_t count)
 {
 {
-	unsigned long val;
+	int val, err;
 
 
-	if (strict_strtoul(buf, 16, &val) || val > 0xff)
+	err = kstrtoint(buf, 16, &val);
+	if (err)
+		return err;
+
+	if (val > 0xff)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (fsp_page_reg_write(psmouse, val))
 	if (fsp_page_reg_write(psmouse, val))
@@ -505,9 +516,14 @@ static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse,
 static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
 static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data,
 					const char *buf, size_t count)
 					const char *buf, size_t count)
 {
 {
-	unsigned long val;
+	unsigned int val;
+	int err;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err)
+		return err;
 
 
-	if (strict_strtoul(buf, 10, &val) || val > 1)
+	if (val > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	fsp_onpad_vscr(psmouse, val);
 	fsp_onpad_vscr(psmouse, val);
@@ -529,9 +545,14 @@ static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse,
 static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
 static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data,
 					const char *buf, size_t count)
 					const char *buf, size_t count)
 {
 {
-	unsigned long val;
+	unsigned int val;
+	int err;
+
+	err = kstrtouint(buf, 10, &val);
+	if (err)
+		return err;
 
 
-	if (strict_strtoul(buf, 10, &val) || val > 1)
+	if (val > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	fsp_onpad_hscr(psmouse, val);
 	fsp_onpad_hscr(psmouse, val);

+ 142 - 55
drivers/input/mouse/synaptics.c

@@ -269,19 +269,49 @@ static int synaptics_query_hardware(struct psmouse *psmouse)
 	return 0;
 	return 0;
 }
 }
 
 
-static int synaptics_set_absolute_mode(struct psmouse *psmouse)
+static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
+{
+	static unsigned char param = 0xc8;
+	struct synaptics_data *priv = psmouse->private;
+
+	if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+		return 0;
+
+	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
+		return -1;
+
+	if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
+		return -1;
+
+	/* Advanced gesture mode also sends multi finger data */
+	priv->capabilities |= BIT(1);
+
+	return 0;
+}
+
+static int synaptics_set_mode(struct psmouse *psmouse)
 {
 {
 	struct synaptics_data *priv = psmouse->private;
 	struct synaptics_data *priv = psmouse->private;
 
 
-	priv->mode = SYN_BIT_ABSOLUTE_MODE;
-	if (SYN_ID_MAJOR(priv->identity) >= 4)
+	priv->mode = 0;
+	if (priv->absolute_mode)
+		priv->mode |= SYN_BIT_ABSOLUTE_MODE;
+	if (priv->disable_gesture)
 		priv->mode |= SYN_BIT_DISABLE_GESTURE;
 		priv->mode |= SYN_BIT_DISABLE_GESTURE;
+	if (psmouse->rate >= 80)
+		priv->mode |= SYN_BIT_HIGH_RATE;
 	if (SYN_CAP_EXTENDED(priv->capabilities))
 	if (SYN_CAP_EXTENDED(priv->capabilities))
 		priv->mode |= SYN_BIT_W_MODE;
 		priv->mode |= SYN_BIT_W_MODE;
 
 
 	if (synaptics_mode_cmd(psmouse, priv->mode))
 	if (synaptics_mode_cmd(psmouse, priv->mode))
 		return -1;
 		return -1;
 
 
+	if (priv->absolute_mode &&
+	    synaptics_set_advanced_gesture_mode(psmouse)) {
+		psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
+		return -1;
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -300,26 +330,6 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
 	synaptics_mode_cmd(psmouse, priv->mode);
 	synaptics_mode_cmd(psmouse, priv->mode);
 }
 }
 
 
-static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
-{
-	static unsigned char param = 0xc8;
-	struct synaptics_data *priv = psmouse->private;
-
-	if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
-			SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
-		return 0;
-
-	if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
-		return -1;
-	if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
-		return -1;
-
-	/* Advanced gesture mode also sends multi finger data */
-	priv->capabilities |= BIT(1);
-
-	return 0;
-}
-
 /*****************************************************************************
 /*****************************************************************************
  *	Synaptics pass-through PS/2 port support
  *	Synaptics pass-through PS/2 port support
  ****************************************************************************/
  ****************************************************************************/
@@ -1143,8 +1153,24 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 {
 {
 	int i;
 	int i;
 
 
+	/* Things that apply to both modes */
 	__set_bit(INPUT_PROP_POINTER, dev->propbit);
 	__set_bit(INPUT_PROP_POINTER, dev->propbit);
+	__set_bit(EV_KEY, dev->evbit);
+	__set_bit(BTN_LEFT, dev->keybit);
+	__set_bit(BTN_RIGHT, dev->keybit);
 
 
+	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+		__set_bit(BTN_MIDDLE, dev->keybit);
+
+	if (!priv->absolute_mode) {
+		/* Relative mode */
+		__set_bit(EV_REL, dev->evbit);
+		__set_bit(REL_X, dev->relbit);
+		__set_bit(REL_Y, dev->relbit);
+		return;
+	}
+
+	/* Absolute mode */
 	__set_bit(EV_ABS, dev->evbit);
 	__set_bit(EV_ABS, dev->evbit);
 	set_abs_position_params(dev, priv, ABS_X, ABS_Y);
 	set_abs_position_params(dev, priv, ABS_X, ABS_Y);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
@@ -1170,20 +1196,14 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
 
 
-	__set_bit(EV_KEY, dev->evbit);
 	__set_bit(BTN_TOUCH, dev->keybit);
 	__set_bit(BTN_TOUCH, dev->keybit);
 	__set_bit(BTN_TOOL_FINGER, dev->keybit);
 	__set_bit(BTN_TOOL_FINGER, dev->keybit);
-	__set_bit(BTN_LEFT, dev->keybit);
-	__set_bit(BTN_RIGHT, dev->keybit);
 
 
 	if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 	if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
 		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
 		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
 		__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
 		__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
 	}
 	}
 
 
-	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
-		__set_bit(BTN_MIDDLE, dev->keybit);
-
 	if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
 	if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
 	    SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 	    SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 		__set_bit(BTN_FORWARD, dev->keybit);
 		__set_bit(BTN_FORWARD, dev->keybit);
@@ -1205,10 +1225,58 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	}
 	}
 }
 }
 
 
+static ssize_t synaptics_show_disable_gesture(struct psmouse *psmouse,
+					      void *data, char *buf)
+{
+	struct synaptics_data *priv = psmouse->private;
+
+	return sprintf(buf, "%c\n", priv->disable_gesture ? '1' : '0');
+}
+
+static ssize_t synaptics_set_disable_gesture(struct psmouse *psmouse,
+					     void *data, const char *buf,
+					     size_t len)
+{
+	struct synaptics_data *priv = psmouse->private;
+	unsigned int value;
+	int err;
+
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
+
+	if (value > 1)
+		return -EINVAL;
+
+	if (value == priv->disable_gesture)
+		return len;
+
+	priv->disable_gesture = value;
+	if (value)
+		priv->mode |= SYN_BIT_DISABLE_GESTURE;
+	else
+		priv->mode &= ~SYN_BIT_DISABLE_GESTURE;
+
+	if (synaptics_mode_cmd(psmouse, priv->mode))
+		return -EIO;
+
+	return len;
+}
+
+PSMOUSE_DEFINE_ATTR(disable_gesture, S_IWUSR | S_IRUGO, NULL,
+		    synaptics_show_disable_gesture,
+		    synaptics_set_disable_gesture);
+
 static void synaptics_disconnect(struct psmouse *psmouse)
 static void synaptics_disconnect(struct psmouse *psmouse)
 {
 {
+	struct synaptics_data *priv = psmouse->private;
+
+	if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity))
+		device_remove_file(&psmouse->ps2dev.serio->dev,
+				   &psmouse_attr_disable_gesture.dattr);
+
 	synaptics_reset(psmouse);
 	synaptics_reset(psmouse);
-	kfree(psmouse->private);
+	kfree(priv);
 	psmouse->private = NULL;
 	psmouse->private = NULL;
 }
 }
 
 
@@ -1245,17 +1313,11 @@ static int synaptics_reconnect(struct psmouse *psmouse)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if (synaptics_set_absolute_mode(psmouse)) {
+	if (synaptics_set_mode(psmouse)) {
 		psmouse_err(psmouse, "Unable to initialize device.\n");
 		psmouse_err(psmouse, "Unable to initialize device.\n");
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		psmouse_err(psmouse,
-			    "Advanced gesture mode reconnect failed.\n");
-		return -1;
-	}
-
 	if (old_priv.identity != priv->identity ||
 	if (old_priv.identity != priv->identity ||
 	    old_priv.model_id != priv->model_id ||
 	    old_priv.model_id != priv->model_id ||
 	    old_priv.capabilities != priv->capabilities ||
 	    old_priv.capabilities != priv->capabilities ||
@@ -1332,20 +1394,18 @@ void __init synaptics_module_init(void)
 	broken_olpc_ec = dmi_check_system(olpc_dmi_table);
 	broken_olpc_ec = dmi_check_system(olpc_dmi_table);
 }
 }
 
 
-int synaptics_init(struct psmouse *psmouse)
+static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
 {
 {
 	struct synaptics_data *priv;
 	struct synaptics_data *priv;
+	int err = -1;
 
 
 	/*
 	/*
-	 * The OLPC XO has issues with Synaptics' absolute mode; similarly to
-	 * the HGPK, it quickly degrades and the hardware becomes jumpy and
-	 * overly sensitive.  Not only that, but the constant packet spew
-	 * (even at a lowered 40pps rate) overloads the EC such that key
-	 * presses on the keyboard are missed.  Given all of that, don't
-	 * even attempt to use Synaptics mode.  Relative mode seems to work
-	 * just fine.
+	 * The OLPC XO has issues with Synaptics' absolute mode; the constant
+	 * packet spew overloads the EC such that key presses on the keyboard
+	 * are missed.  Given that, don't even attempt to use Absolute mode.
+	 * Relative mode seems to work just fine.
 	 */
 	 */
-	if (broken_olpc_ec) {
+	if (absolute_mode && broken_olpc_ec) {
 		psmouse_info(psmouse,
 		psmouse_info(psmouse,
 			     "OLPC XO detected, not enabling Synaptics protocol.\n");
 			     "OLPC XO detected, not enabling Synaptics protocol.\n");
 		return -ENODEV;
 		return -ENODEV;
@@ -1362,13 +1422,12 @@ int synaptics_init(struct psmouse *psmouse)
 		goto init_fail;
 		goto init_fail;
 	}
 	}
 
 
-	if (synaptics_set_absolute_mode(psmouse)) {
-		psmouse_err(psmouse, "Unable to initialize device.\n");
-		goto init_fail;
-	}
+	priv->absolute_mode = absolute_mode;
+	if (SYN_ID_DISGEST_SUPPORTED(priv->identity))
+		priv->disable_gesture = true;
 
 
-	if (synaptics_set_advanced_gesture_mode(psmouse)) {
-		psmouse_err(psmouse, "Advanced gesture mode init failed.\n");
+	if (synaptics_set_mode(psmouse)) {
+		psmouse_err(psmouse, "Unable to initialize device.\n");
 		goto init_fail;
 		goto init_fail;
 	}
 	}
 
 
@@ -1393,12 +1452,19 @@ int synaptics_init(struct psmouse *psmouse)
 	psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
 	psmouse->model = ((priv->model_id & 0x00ff0000) >> 8) |
 			  (priv->model_id & 0x000000ff);
 			  (priv->model_id & 0x000000ff);
 
 
-	psmouse->protocol_handler = synaptics_process_byte;
+	if (absolute_mode) {
+		psmouse->protocol_handler = synaptics_process_byte;
+		psmouse->pktsize = 6;
+	} else {
+		/* Relative mode follows standard PS/2 mouse protocol */
+		psmouse->protocol_handler = psmouse_process_byte;
+		psmouse->pktsize = 3;
+	}
+
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->disconnect = synaptics_disconnect;
 	psmouse->disconnect = synaptics_disconnect;
 	psmouse->reconnect = synaptics_reconnect;
 	psmouse->reconnect = synaptics_reconnect;
 	psmouse->cleanup = synaptics_reset;
 	psmouse->cleanup = synaptics_reset;
-	psmouse->pktsize = 6;
 	/* Synaptics can usually stay in sync without extra help */
 	/* Synaptics can usually stay in sync without extra help */
 	psmouse->resync_time = 0;
 	psmouse->resync_time = 0;
 
 
@@ -1417,11 +1483,32 @@ int synaptics_init(struct psmouse *psmouse)
 		psmouse->rate = 40;
 		psmouse->rate = 40;
 	}
 	}
 
 
+	if (!priv->absolute_mode && SYN_ID_DISGEST_SUPPORTED(priv->identity)) {
+		err = device_create_file(&psmouse->ps2dev.serio->dev,
+					 &psmouse_attr_disable_gesture.dattr);
+		if (err) {
+			psmouse_err(psmouse,
+				    "Failed to create disable_gesture attribute (%d)",
+				    err);
+			goto init_fail;
+		}
+	}
+
 	return 0;
 	return 0;
 
 
  init_fail:
  init_fail:
 	kfree(priv);
 	kfree(priv);
-	return -1;
+	return err;
+}
+
+int synaptics_init(struct psmouse *psmouse)
+{
+	return __synaptics_init(psmouse, true);
+}
+
+int synaptics_init_relative(struct psmouse *psmouse)
+{
+	return __synaptics_init(psmouse, false);
 }
 }
 
 
 bool synaptics_supported(void)
 bool synaptics_supported(void)

+ 5 - 0
drivers/input/mouse/synaptics.h

@@ -100,6 +100,7 @@
 #define SYN_ID_MINOR(i)			(((i) >> 16) & 0xff)
 #define SYN_ID_MINOR(i)			(((i) >> 16) & 0xff)
 #define SYN_ID_FULL(i)			((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i))
 #define SYN_ID_FULL(i)			((SYN_ID_MAJOR(i) << 8) | SYN_ID_MINOR(i))
 #define SYN_ID_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)
 #define SYN_ID_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)
+#define SYN_ID_DISGEST_SUPPORTED(i)	(SYN_ID_MAJOR(i) >= 4)
 
 
 /* synaptics special commands */
 /* synaptics special commands */
 #define SYN_PS_SET_MODE2		0x14
 #define SYN_PS_SET_MODE2		0x14
@@ -159,6 +160,9 @@ struct synaptics_data {
 	unsigned char mode;			/* current mode byte */
 	unsigned char mode;			/* current mode byte */
 	int scroll;
 	int scroll;
 
 
+	bool absolute_mode;			/* run in Absolute mode */
+	bool disable_gesture;			/* disable gestures */
+
 	struct serio *pt_port;			/* Pass-through serio port */
 	struct serio *pt_port;			/* Pass-through serio port */
 
 
 	struct synaptics_mt_state mt_state;	/* Current mt finger state */
 	struct synaptics_mt_state mt_state;	/* Current mt finger state */
@@ -175,6 +179,7 @@ struct synaptics_data {
 void synaptics_module_init(void);
 void synaptics_module_init(void);
 int synaptics_detect(struct psmouse *psmouse, bool set_properties);
 int synaptics_detect(struct psmouse *psmouse, bool set_properties);
 int synaptics_init(struct psmouse *psmouse);
 int synaptics_init(struct psmouse *psmouse);
+int synaptics_init_relative(struct psmouse *psmouse);
 void synaptics_reset(struct psmouse *psmouse);
 void synaptics_reset(struct psmouse *psmouse);
 bool synaptics_supported(void);
 bool synaptics_supported(void);
 
 

+ 12 - 5
drivers/input/mouse/trackpoint.c

@@ -89,10 +89,12 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
 	struct trackpoint_data *tp = psmouse->private;
 	struct trackpoint_data *tp = psmouse->private;
 	struct trackpoint_attr_data *attr = data;
 	struct trackpoint_attr_data *attr = data;
 	unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
 	unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
-	unsigned long value;
+	unsigned char value;
+	int err;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 255)
-		return -EINVAL;
+	err = kstrtou8(buf, 10, &value);
+	if (err)
+		return err;
 
 
 	*field = value;
 	*field = value;
 	trackpoint_write(&psmouse->ps2dev, attr->command, value);
 	trackpoint_write(&psmouse->ps2dev, attr->command, value);
@@ -115,9 +117,14 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
 	struct trackpoint_data *tp = psmouse->private;
 	struct trackpoint_data *tp = psmouse->private;
 	struct trackpoint_attr_data *attr = data;
 	struct trackpoint_attr_data *attr = data;
 	unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
 	unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset);
-	unsigned long value;
+	unsigned int value;
+	int err;
+
+	err = kstrtouint(buf, 10, &value);
+	if (err)
+		return err;
 
 
-	if (strict_strtoul(buf, 10, &value) || value > 1)
+	if (value > 1)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (attr->inverted)
 	if (attr->inverted)

+ 1 - 12
drivers/input/serio/altera_ps2.c

@@ -196,18 +196,7 @@ static struct platform_driver altera_ps2_driver = {
 		.of_match_table = altera_ps2_match,
 		.of_match_table = altera_ps2_match,
 	},
 	},
 };
 };
-
-static int __init altera_ps2_init(void)
-{
-	return platform_driver_register(&altera_ps2_driver);
-}
-module_init(altera_ps2_init);
-
-static void __exit altera_ps2_exit(void)
-{
-	platform_driver_unregister(&altera_ps2_driver);
-}
-module_exit(altera_ps2_exit);
+module_platform_driver(altera_ps2_driver);
 
 
 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
 MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");

+ 1 - 13
drivers/input/serio/at32psif.c

@@ -358,19 +358,7 @@ static struct platform_driver psif_driver = {
 	.suspend	= psif_suspend,
 	.suspend	= psif_suspend,
 	.resume		= psif_resume,
 	.resume		= psif_resume,
 };
 };
-
-static int __init psif_init(void)
-{
-	return platform_driver_probe(&psif_driver, psif_probe);
-}
-
-static void __exit psif_exit(void)
-{
-	platform_driver_unregister(&psif_driver);
-}
-
-module_init(psif_init);
-module_exit(psif_exit);
+module_platform_driver(psif_driver);
 
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");
 MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver");

+ 15 - 8
drivers/input/serio/i8042.c

@@ -991,7 +991,7 @@ static int i8042_controller_init(void)
  * Reset the controller and reset CRT to the original value set by BIOS.
  * Reset the controller and reset CRT to the original value set by BIOS.
  */
  */
 
 
-static void i8042_controller_reset(void)
+static void i8042_controller_reset(bool force_reset)
 {
 {
 	i8042_flush();
 	i8042_flush();
 
 
@@ -1016,7 +1016,7 @@ static void i8042_controller_reset(void)
  * Reset the controller if requested.
  * Reset the controller if requested.
  */
  */
 
 
-	if (i8042_reset)
+	if (i8042_reset || force_reset)
 		i8042_controller_selftest();
 		i8042_controller_selftest();
 
 
 /*
 /*
@@ -1139,9 +1139,9 @@ static int i8042_controller_resume(bool force_reset)
  * upsetting it.
  * upsetting it.
  */
  */
 
 
-static int i8042_pm_reset(struct device *dev)
+static int i8042_pm_suspend(struct device *dev)
 {
 {
-	i8042_controller_reset();
+	i8042_controller_reset(true);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1163,13 +1163,20 @@ static int i8042_pm_thaw(struct device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
+static int i8042_pm_reset(struct device *dev)
+{
+	i8042_controller_reset(false);
+
+	return 0;
+}
+
 static int i8042_pm_restore(struct device *dev)
 static int i8042_pm_restore(struct device *dev)
 {
 {
 	return i8042_controller_resume(false);
 	return i8042_controller_resume(false);
 }
 }
 
 
 static const struct dev_pm_ops i8042_pm_ops = {
 static const struct dev_pm_ops i8042_pm_ops = {
-	.suspend	= i8042_pm_reset,
+	.suspend	= i8042_pm_suspend,
 	.resume		= i8042_pm_resume,
 	.resume		= i8042_pm_resume,
 	.thaw		= i8042_pm_thaw,
 	.thaw		= i8042_pm_thaw,
 	.poweroff	= i8042_pm_reset,
 	.poweroff	= i8042_pm_reset,
@@ -1185,7 +1192,7 @@ static const struct dev_pm_ops i8042_pm_ops = {
 
 
 static void i8042_shutdown(struct platform_device *dev)
 static void i8042_shutdown(struct platform_device *dev)
 {
 {
-	i8042_controller_reset();
+	i8042_controller_reset(false);
 }
 }
 
 
 static int __init i8042_create_kbd_port(void)
 static int __init i8042_create_kbd_port(void)
@@ -1424,7 +1431,7 @@ static int __init i8042_probe(struct platform_device *dev)
  out_fail:
  out_fail:
 	i8042_free_aux_ports();	/* in case KBD failed but AUX not */
 	i8042_free_aux_ports();	/* in case KBD failed but AUX not */
 	i8042_free_irqs();
 	i8042_free_irqs();
-	i8042_controller_reset();
+	i8042_controller_reset(false);
 	i8042_platform_device = NULL;
 	i8042_platform_device = NULL;
 
 
 	return error;
 	return error;
@@ -1434,7 +1441,7 @@ static int __devexit i8042_remove(struct platform_device *dev)
 {
 {
 	i8042_unregister_ports();
 	i8042_unregister_ports();
 	i8042_free_irqs();
 	i8042_free_irqs();
-	i8042_controller_reset();
+	i8042_controller_reset(false);
 	i8042_platform_device = NULL;
 	i8042_platform_device = NULL;
 
 
 	return 0;
 	return 0;

+ 1 - 13
drivers/input/serio/rpckbd.c

@@ -143,16 +143,4 @@ static struct platform_driver rpckbd_driver = {
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 	},
 	},
 };
 };
-
-static int __init rpckbd_init(void)
-{
-	return platform_driver_register(&rpckbd_driver);
-}
-
-static void __exit rpckbd_exit(void)
-{
-	platform_driver_unregister(&rpckbd_driver);
-}
-
-module_init(rpckbd_init);
-module_exit(rpckbd_exit);
+module_platform_driver(rpckbd_driver);

+ 1 - 13
drivers/input/serio/xilinx_ps2.c

@@ -369,19 +369,7 @@ static struct platform_driver xps2_of_driver = {
 	.probe		= xps2_of_probe,
 	.probe		= xps2_of_probe,
 	.remove		= __devexit_p(xps2_of_remove),
 	.remove		= __devexit_p(xps2_of_remove),
 };
 };
-
-static int __init xps2_init(void)
-{
-	return platform_driver_register(&xps2_of_driver);
-}
-
-static void __exit xps2_cleanup(void)
-{
-	platform_driver_unregister(&xps2_of_driver);
-}
-
-module_init(xps2_init);
-module_exit(xps2_cleanup);
+module_platform_driver(xps2_of_driver);
 
 
 MODULE_AUTHOR("Xilinx, Inc.");
 MODULE_AUTHOR("Xilinx, Inc.");
 MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
 MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");

+ 19 - 15
drivers/input/tablet/aiptek.c

@@ -1198,9 +1198,9 @@ static ssize_t
 store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	long x;
+	int x;
 
 
-	if (strict_strtol(buf, 10, &x)) {
+	if (kstrtoint(buf, 10, &x)) {
 		size_t len = buf[count - 1] == '\n' ? count - 1 : count;
 		size_t len = buf[count - 1] == '\n' ? count - 1 : count;
 
 
 		if (strncmp(buf, "disable", len))
 		if (strncmp(buf, "disable", len))
@@ -1240,9 +1240,9 @@ static ssize_t
 store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	long y;
+	int y;
 
 
-	if (strict_strtol(buf, 10, &y)) {
+	if (kstrtoint(buf, 10, &y)) {
 		size_t len = buf[count - 1] == '\n' ? count - 1 : count;
 		size_t len = buf[count - 1] == '\n' ? count - 1 : count;
 
 
 		if (strncmp(buf, "disable", len))
 		if (strncmp(buf, "disable", len))
@@ -1277,12 +1277,13 @@ static ssize_t
 store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	long j;
+	int err, j;
 
 
-	if (strict_strtol(buf, 10, &j))
-		return -EINVAL;
+	err = kstrtoint(buf, 10, &j);
+	if (err)
+		return err;
 
 
-	aiptek->newSetting.jitterDelay = (int)j;
+	aiptek->newSetting.jitterDelay = j;
 	return count;
 	return count;
 }
 }
 
 
@@ -1306,12 +1307,13 @@ static ssize_t
 store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	long d;
+	int err, d;
 
 
-	if (strict_strtol(buf, 10, &d))
-		return -EINVAL;
+	err = kstrtoint(buf, 10, &d);
+	if (err)
+		return err;
 
 
-	aiptek->newSetting.programmableDelay = (int)d;
+	aiptek->newSetting.programmableDelay = d;
 	return count;
 	return count;
 }
 }
 
 
@@ -1557,11 +1559,13 @@ static ssize_t
 store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	struct aiptek *aiptek = dev_get_drvdata(dev);
-	long w;
+	int err, w;
 
 
-	if (strict_strtol(buf, 10, &w)) return -EINVAL;
+	err = kstrtoint(buf, 10, &w);
+	if (err)
+		return err;
 
 
-	aiptek->newSetting.wheel = (int)w;
+	aiptek->newSetting.wheel = w;
 	return count;
 	return count;
 }
 }
 
 

+ 91 - 10
drivers/input/tablet/wacom_sys.c

@@ -28,7 +28,9 @@
 #define HID_USAGE_Y_TILT		0x3e
 #define HID_USAGE_Y_TILT		0x3e
 #define HID_USAGE_FINGER		0x22
 #define HID_USAGE_FINGER		0x22
 #define HID_USAGE_STYLUS		0x20
 #define HID_USAGE_STYLUS		0x20
-#define HID_COLLECTION			0xc0
+#define HID_COLLECTION			0xa1
+#define HID_COLLECTION_LOGICAL		0x02
+#define HID_COLLECTION_END		0xc0
 
 
 enum {
 enum {
 	WCM_UNDEFINED = 0,
 	WCM_UNDEFINED = 0,
@@ -66,7 +68,8 @@ static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
 	do {
 	do {
 		retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 		retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 				USB_REQ_GET_REPORT,
 				USB_REQ_GET_REPORT,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+				USB_DIR_IN | USB_TYPE_CLASS |
+				USB_RECIP_INTERFACE,
 				(type << 8) + id,
 				(type << 8) + id,
 				intf->altsetting[0].desc.bInterfaceNumber,
 				intf->altsetting[0].desc.bInterfaceNumber,
 				buf, size, 100);
 				buf, size, 100);
@@ -164,7 +167,70 @@ static void wacom_close(struct input_dev *dev)
 		usb_autopm_put_interface(wacom->intf);
 		usb_autopm_put_interface(wacom->intf);
 }
 }
 
 
-static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
+static int wacom_parse_logical_collection(unsigned char *report,
+					  struct wacom_features *features)
+{
+	int length = 0;
+
+	if (features->type == BAMBOO_PT) {
+
+		/* Logical collection is only used by 3rd gen Bamboo Touch */
+		features->pktlen = WACOM_PKGLEN_BBTOUCH3;
+		features->device_type = BTN_TOOL_DOUBLETAP;
+
+		/*
+		 * Stylus and Touch have same active area
+		 * so compute physical size based on stylus
+		 * data before its overwritten.
+		 */
+		features->x_phy =
+			(features->x_max * features->x_resolution) / 100;
+		features->y_phy =
+			(features->y_max * features->y_resolution) / 100;
+
+		features->x_max = features->y_max =
+			get_unaligned_le16(&report[10]);
+
+		length = 11;
+	}
+	return length;
+}
+
+/*
+ * Interface Descriptor of wacom devices can be incomplete and
+ * inconsistent so wacom_features table is used to store stylus
+ * device's packet lengths, various maximum values, and tablet
+ * resolution based on product ID's.
+ *
+ * For devices that contain 2 interfaces, wacom_features table is
+ * inaccurate for the touch interface.  Since the Interface Descriptor
+ * for touch interfaces has pretty complete data, this function exists
+ * to query tablet for this missing information instead of hard coding in
+ * an additional table.
+ *
+ * A typical Interface Descriptor for a stylus will contain a
+ * boot mouse application collection that is not of interest and this
+ * function will ignore it.
+ *
+ * It also contains a digitizer application collection that also is not
+ * of interest since any information it contains would be duplicate
+ * of what is in wacom_features. Usually it defines a report of an array
+ * of bytes that could be used as max length of the stylus packet returned.
+ * If it happens to define a Digitizer-Stylus Physical Collection then
+ * the X and Y logical values contain valid data but it is ignored.
+ *
+ * A typical Interface Descriptor for a touch interface will contain a
+ * Digitizer-Finger Physical Collection which will define both logical
+ * X/Y maximum as well as the physical size of tablet. Since touch
+ * interfaces haven't supported pressure or distance, this is enough
+ * information to override invalid values in the wacom_features table.
+ *
+ * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical
+ * Collection. Instead they define a Logical Collection with a single
+ * Logical Maximum for both X and Y.
+ */
+static int wacom_parse_hid(struct usb_interface *intf,
+			   struct hid_descriptor *hid_desc,
 			   struct wacom_features *features)
 			   struct wacom_features *features)
 {
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -244,8 +310,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 						/* penabled only accepts exact bytes of data */
 						/* penabled only accepts exact bytes of data */
 						if (features->type == TABLETPC2FG)
 						if (features->type == TABLETPC2FG)
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-						if (features->type == BAMBOO_PT)
-							features->pktlen = WACOM_PKGLEN_BBFUN;
 						features->device_type = BTN_TOOL_PEN;
 						features->device_type = BTN_TOOL_PEN;
 						features->x_max =
 						features->x_max =
 							get_unaligned_le16(&report[i + 3]);
 							get_unaligned_le16(&report[i + 3]);
@@ -287,8 +351,6 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 						/* penabled only accepts exact bytes of data */
 						/* penabled only accepts exact bytes of data */
 						if (features->type == TABLETPC2FG)
 						if (features->type == TABLETPC2FG)
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
-						if (features->type == BAMBOO_PT)
-							features->pktlen = WACOM_PKGLEN_BBFUN;
 						features->device_type = BTN_TOOL_PEN;
 						features->device_type = BTN_TOOL_PEN;
 						features->y_max =
 						features->y_max =
 							get_unaligned_le16(&report[i + 3]);
 							get_unaligned_le16(&report[i + 3]);
@@ -302,6 +364,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 				i++;
 				i++;
 				break;
 				break;
 
 
+			/*
+			 * Requiring Stylus Usage will ignore boot mouse
+			 * X/Y values and some cases of invalid Digitizer X/Y
+			 * values commonly reported.
+			 */
 			case HID_USAGE_STYLUS:
 			case HID_USAGE_STYLUS:
 				pen = 1;
 				pen = 1;
 				i++;
 				i++;
@@ -309,10 +376,20 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 			}
 			}
 			break;
 			break;
 
 
-		case HID_COLLECTION:
+		case HID_COLLECTION_END:
 			/* reset UsagePage and Finger */
 			/* reset UsagePage and Finger */
 			finger = usage = 0;
 			finger = usage = 0;
 			break;
 			break;
+
+		case HID_COLLECTION:
+			i++;
+			switch (report[i]) {
+			case HID_COLLECTION_LOGICAL:
+				i += wacom_parse_logical_collection(&report[i],
+								    features);
+				break;
+			}
+			break;
 		}
 		}
 	}
 	}
 
 
@@ -348,7 +425,8 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
 						WAC_HID_FEATURE_REPORT,
 						WAC_HID_FEATURE_REPORT,
 						report_id, rep_data, 4, 1);
 						report_id, rep_data, 4, 1);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
-	} else if (features->type != TABLETPC) {
+	} else if (features->type != TABLETPC &&
+		   features->device_type == BTN_TOOL_PEN) {
 		do {
 		do {
 			rep_data[0] = 2;
 			rep_data[0] = 2;
 			rep_data[1] = 2;
 			rep_data[1] = 2;
@@ -485,7 +563,8 @@ static int wacom_led_control(struct wacom *wacom)
 	if (!buf)
 	if (!buf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	if (wacom->wacom_wac.features.type == WACOM_21UX2)
+	if (wacom->wacom_wac.features.type == WACOM_21UX2 ||
+	    wacom->wacom_wac.features.type == WACOM_24HD)
 		led = (wacom->led.select[1] << 4) | 0x40;
 		led = (wacom->led.select[1] << 4) | 0x40;
 
 
 	led |=  wacom->led.select[0] | 0x4;
 	led |=  wacom->led.select[0] | 0x4;
@@ -704,6 +783,7 @@ static int wacom_initialize_leds(struct wacom *wacom)
 					   &intuos4_led_attr_group);
 					   &intuos4_led_attr_group);
 		break;
 		break;
 
 
+	case WACOM_24HD:
 	case WACOM_21UX2:
 	case WACOM_21UX2:
 		wacom->led.select[0] = 0;
 		wacom->led.select[0] = 0;
 		wacom->led.select[1] = 0;
 		wacom->led.select[1] = 0;
@@ -738,6 +818,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
 				   &intuos4_led_attr_group);
 				   &intuos4_led_attr_group);
 		break;
 		break;
 
 
+	case WACOM_24HD:
 	case WACOM_21UX2:
 	case WACOM_21UX2:
 		sysfs_remove_group(&wacom->intf->dev.kobj,
 		sysfs_remove_group(&wacom->intf->dev.kobj,
 				   &cintiq_led_attr_group);
 				   &cintiq_led_attr_group);

+ 176 - 11
drivers/input/tablet/wacom_wac.c

@@ -452,7 +452,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
 	if ((data[1] & 0xb8) == 0xa0) {
 	if ((data[1] & 0xb8) == 0xa0) {
 		t = (data[6] << 2) | ((data[7] >> 6) & 3);
 		t = (data[6] << 2) | ((data[7] >> 6) & 3);
 		if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
 		if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
-		    features->type == WACOM_21UX2) {
+		    features->type == WACOM_21UX2 || features->type == WACOM_24HD) {
 			t = (t << 1) | (data[1] & 1);
 			t = (t << 1) | (data[1] & 1);
 		}
 		}
 		input_report_abs(input, ABS_PRESSURE, t);
 		input_report_abs(input, ABS_PRESSURE, t);
@@ -519,6 +519,56 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
 				input_report_key(input, wacom->tool[1], 0);
 				input_report_key(input, wacom->tool[1], 0);
 				input_report_abs(input, ABS_MISC, 0);
 				input_report_abs(input, ABS_MISC, 0);
 			}
 			}
+		} else if (features->type == WACOM_24HD) {
+			input_report_key(input, BTN_0, (data[6] & 0x01));
+			input_report_key(input, BTN_1, (data[6] & 0x02));
+			input_report_key(input, BTN_2, (data[6] & 0x04));
+			input_report_key(input, BTN_3, (data[6] & 0x08));
+			input_report_key(input, BTN_4, (data[6] & 0x10));
+			input_report_key(input, BTN_5, (data[6] & 0x20));
+			input_report_key(input, BTN_6, (data[6] & 0x40));
+			input_report_key(input, BTN_7, (data[6] & 0x80));
+			input_report_key(input, BTN_8, (data[8] & 0x01));
+			input_report_key(input, BTN_9, (data[8] & 0x02));
+			input_report_key(input, BTN_A, (data[8] & 0x04));
+			input_report_key(input, BTN_B, (data[8] & 0x08));
+			input_report_key(input, BTN_C, (data[8] & 0x10));
+			input_report_key(input, BTN_X, (data[8] & 0x20));
+			input_report_key(input, BTN_Y, (data[8] & 0x40));
+			input_report_key(input, BTN_Z, (data[8] & 0x80));
+
+			/*
+			 * Three "buttons" are available on the 24HD which are
+			 * physically implemented as a touchstrip. Each button
+			 * is approximately 3 bits wide with a 2 bit spacing.
+			 * The raw touchstrip bits are stored at:
+			 *    ((data[3] & 0x1f) << 8) | data[4])
+			 */
+			input_report_key(input, KEY_PROG1, data[4] & 0x07);
+			input_report_key(input, KEY_PROG2, data[4] & 0xE0);
+			input_report_key(input, KEY_PROG3, data[3] & 0x1C);
+
+			if (data[1] & 0x80) {
+				input_report_abs(input, ABS_WHEEL, (data[1] & 0x7f));
+			} else {
+				/* Out of proximity, clear wheel value. */
+				input_report_abs(input, ABS_WHEEL, 0);
+			}
+
+			if (data[2] & 0x80) {
+				input_report_abs(input, ABS_THROTTLE, (data[2] & 0x7f));
+			} else {
+				/* Out of proximity, clear second wheel value. */
+				input_report_abs(input, ABS_THROTTLE, 0);
+			}
+
+			if (data[1] | data[2] | (data[3] & 0x1f) | data[4] | data[6] | data[8]) {
+				input_report_key(input, wacom->tool[1], 1);
+				input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+			} else {
+				input_report_key(input, wacom->tool[1], 0);
+				input_report_abs(input, ABS_MISC, 0);
+			}
 		} else {
 		} else {
 			if (features->type == WACOM_21UX2) {
 			if (features->type == WACOM_21UX2) {
 				input_report_key(input, BTN_0, (data[5] & 0x01));
 				input_report_key(input, BTN_0, (data[5] & 0x01));
@@ -799,6 +849,9 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
 	unsigned char *data = wacom->data;
 	unsigned char *data = wacom->data;
 	int i;
 	int i;
 
 
+	if (data[0] != 0x02)
+	    return 0;
+
 	for (i = 0; i < 2; i++) {
 	for (i = 0; i < 2; i++) {
 		int offset = (data[1] & 0x80) ? (8 * i) : (9 * i);
 		int offset = (data[1] & 0x80) ? (8 * i) : (9 * i);
 		bool touch = data[offset + 3] & 0x80;
 		bool touch = data[offset + 3] & 0x80;
@@ -837,18 +890,77 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
 	return 0;
 	return 0;
 }
 }
 
 
+static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
+{
+	struct input_dev *input = wacom->input;
+	int slot_id = data[0] - 2;  /* data[0] is between 2 and 17 */
+	bool touch = data[1] & 0x80;
+
+	touch = touch && !wacom->shared->stylus_in_proximity;
+
+	input_mt_slot(input, slot_id);
+	input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+	if (touch) {
+		int x = (data[2] << 4) | (data[4] >> 4);
+		int y = (data[3] << 4) | (data[4] & 0x0f);
+		int w = data[6];
+
+		input_report_abs(input, ABS_MT_POSITION_X, x);
+		input_report_abs(input, ABS_MT_POSITION_Y, y);
+		input_report_abs(input, ABS_MT_TOUCH_MAJOR, w);
+	}
+}
+
+static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
+{
+	struct input_dev *input = wacom->input;
+
+	input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+	input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+	input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+}
+
+static int wacom_bpt3_touch(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int count = data[1] & 0x03;
+	int i;
+
+	if (data[0] != 0x02)
+	    return 0;
+
+	/* data has up to 7 fixed sized 8-byte messages starting at data[2] */
+	for (i = 0; i < count; i++) {
+		int offset = (8 * i) + 2;
+		int msg_id = data[offset];
+
+		if (msg_id >= 2 && msg_id <= 17)
+			wacom_bpt3_touch_msg(wacom, data + offset);
+		else if (msg_id == 128)
+			wacom_bpt3_button_msg(wacom, data + offset);
+
+	}
+
+	input_mt_report_pointer_emulation(input, true);
+
+	input_sync(input);
+
+	return 0;
+}
+
 static int wacom_bpt_pen(struct wacom_wac *wacom)
 static int wacom_bpt_pen(struct wacom_wac *wacom)
 {
 {
 	struct input_dev *input = wacom->input;
 	struct input_dev *input = wacom->input;
 	unsigned char *data = wacom->data;
 	unsigned char *data = wacom->data;
 	int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
 	int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
 
 
-	/*
-	 * Similar to Graphire protocol, data[1] & 0x20 is proximity and
-	 * data[1] & 0x18 is tool ID.  0x30 is safety check to ignore
-	 * 2 unused tool ID's.
-	 */
-	prox = (data[1] & 0x30) == 0x30;
+	if (data[0] != 0x02)
+	    return 0;
+
+	prox = (data[1] & 0x20) == 0x20;
 
 
 	/*
 	/*
 	 * All reports shared between PEN and RUBBER tool must be
 	 * All reports shared between PEN and RUBBER tool must be
@@ -912,7 +1024,9 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
 {
 {
 	if (len == WACOM_PKGLEN_BBTOUCH)
 	if (len == WACOM_PKGLEN_BBTOUCH)
 		return wacom_bpt_touch(wacom);
 		return wacom_bpt_touch(wacom);
-	else if (len == WACOM_PKGLEN_BBFUN)
+	else if (len == WACOM_PKGLEN_BBTOUCH3)
+		return wacom_bpt3_touch(wacom);
+	else if (len == WACOM_PKGLEN_BBFUN || len == WACOM_PKGLEN_BBPEN)
 		return wacom_bpt_pen(wacom);
 		return wacom_bpt_pen(wacom);
 
 
 	return 0;
 	return 0;
@@ -955,6 +1069,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 	case CINTIQ:
 	case CINTIQ:
 	case WACOM_BEE:
 	case WACOM_BEE:
 	case WACOM_21UX2:
 	case WACOM_21UX2:
+	case WACOM_24HD:
 		sync = wacom_intuos_irq(wacom_wac);
 		sync = wacom_intuos_irq(wacom_wac);
 		break;
 		break;
 
 
@@ -1031,9 +1146,9 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 	    features->type == BAMBOO_PT)
 	    features->type == BAMBOO_PT)
 		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
 
-	/* quirks for bamboo touch */
+	/* quirk for bamboo touch with 2 low res touches */
 	if (features->type == BAMBOO_PT &&
 	if (features->type == BAMBOO_PT &&
-	    features->device_type == BTN_TOOL_DOUBLETAP) {
+	    features->pktlen == WACOM_PKGLEN_BBTOUCH) {
 		features->x_max <<= 5;
 		features->x_max <<= 5;
 		features->y_max <<= 5;
 		features->y_max <<= 5;
 		features->x_fuzz <<= 5;
 		features->x_fuzz <<= 5;
@@ -1110,6 +1225,26 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 		__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 		break;
 		break;
 
 
+	case WACOM_24HD:
+		__set_bit(BTN_A, input_dev->keybit);
+		__set_bit(BTN_B, input_dev->keybit);
+		__set_bit(BTN_C, input_dev->keybit);
+		__set_bit(BTN_X, input_dev->keybit);
+		__set_bit(BTN_Y, input_dev->keybit);
+		__set_bit(BTN_Z, input_dev->keybit);
+
+		for (i = 0; i < 10; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+
+		__set_bit(KEY_PROG1, input_dev->keybit);
+		__set_bit(KEY_PROG2, input_dev->keybit);
+		__set_bit(KEY_PROG3, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+		wacom_setup_cintiq(wacom_wac);
+		break;
+
 	case WACOM_21UX2:
 	case WACOM_21UX2:
 		__set_bit(BTN_A, input_dev->keybit);
 		__set_bit(BTN_A, input_dev->keybit);
 		__set_bit(BTN_B, input_dev->keybit);
 		__set_bit(BTN_B, input_dev->keybit);
@@ -1240,7 +1375,21 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
 
 
-			input_mt_init_slots(input_dev, 2);
+			if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
+				__set_bit(BTN_TOOL_TRIPLETAP,
+					  input_dev->keybit);
+				__set_bit(BTN_TOOL_QUADTAP,
+					  input_dev->keybit);
+
+				input_mt_init_slots(input_dev, 16);
+
+				input_set_abs_params(input_dev,
+						     ABS_MT_TOUCH_MAJOR,
+						     0, 255, 0, 0);
+			} else {
+				input_mt_init_slots(input_dev, 2);
+			}
+
 			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
 			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
 					     0, features->x_max,
 					     0, features->x_max,
 					     features->x_fuzz, 0);
 					     features->x_fuzz, 0);
@@ -1425,6 +1574,9 @@ static const struct wacom_features wacom_features_0xBB =
 static const struct wacom_features wacom_features_0xBC =
 static const struct wacom_features wacom_features_0xBC =
 	{ "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047,
 	{ "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047,
 	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xF4 =
+	{ "Wacom Cintiq 24HD",    WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+	  63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x3F =
 static const struct wacom_features wacom_features_0x3F =
 	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
 	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
 	  63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 	  63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -1509,6 +1661,15 @@ static const struct wacom_features wacom_features_0xDA =
 static struct wacom_features wacom_features_0xDB =
 static struct wacom_features wacom_features_0xDB =
 	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
 	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13700, 1023,
 	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 	  31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xDD =
+        { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN,     14720,  9200, 1023,
+          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xDE =
+        { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN,    14720,  9200, 1023,
+          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xDF =
+        { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN,    21648, 13700, 1023,
+          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x6004 =
 static const struct wacom_features wacom_features_0x6004 =
 	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
 	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1604,6 +1765,9 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0xD8) },
 	{ USB_DEVICE_WACOM(0xD8) },
 	{ USB_DEVICE_WACOM(0xDA) },
 	{ USB_DEVICE_WACOM(0xDA) },
 	{ USB_DEVICE_WACOM(0xDB) },
 	{ USB_DEVICE_WACOM(0xDB) },
+	{ USB_DEVICE_WACOM(0xDD) },
+	{ USB_DEVICE_WACOM(0xDE) },
+	{ USB_DEVICE_WACOM(0xDF) },
 	{ USB_DEVICE_WACOM(0xF0) },
 	{ USB_DEVICE_WACOM(0xF0) },
 	{ USB_DEVICE_WACOM(0xCC) },
 	{ USB_DEVICE_WACOM(0xCC) },
 	{ USB_DEVICE_WACOM(0x90) },
 	{ USB_DEVICE_WACOM(0x90) },
@@ -1616,6 +1780,7 @@ const struct usb_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0xE6) },
 	{ USB_DEVICE_WACOM(0xE6) },
 	{ USB_DEVICE_WACOM(0xEC) },
 	{ USB_DEVICE_WACOM(0xEC) },
 	{ USB_DEVICE_WACOM(0x47) },
 	{ USB_DEVICE_WACOM(0x47) },
+	{ USB_DEVICE_WACOM(0xF4) },
 	{ USB_DEVICE_LENOVO(0x6004) },
 	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
 	{ }
 };
 };

+ 4 - 1
drivers/input/tablet/wacom_wac.h

@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/types.h>
 
 
 /* maximum packet length for USB devices */
 /* maximum packet length for USB devices */
-#define WACOM_PKGLEN_MAX	32
+#define WACOM_PKGLEN_MAX	64
 
 
 /* packet length for individual models */
 /* packet length for individual models */
 #define WACOM_PKGLEN_PENPRTN	 7
 #define WACOM_PKGLEN_PENPRTN	 7
@@ -22,6 +22,8 @@
 #define WACOM_PKGLEN_TPC1FG	 5
 #define WACOM_PKGLEN_TPC1FG	 5
 #define WACOM_PKGLEN_TPC2FG	14
 #define WACOM_PKGLEN_TPC2FG	14
 #define WACOM_PKGLEN_BBTOUCH	20
 #define WACOM_PKGLEN_BBTOUCH	20
+#define WACOM_PKGLEN_BBTOUCH3	64
+#define WACOM_PKGLEN_BBPEN	10
 
 
 /* device IDs */
 /* device IDs */
 #define STYLUS_DEVICE_ID	0x02
 #define STYLUS_DEVICE_ID	0x02
@@ -57,6 +59,7 @@ enum {
 	INTUOS4S,
 	INTUOS4S,
 	INTUOS4,
 	INTUOS4,
 	INTUOS4L,
 	INTUOS4L,
+	WACOM_24HD,
 	WACOM_21UX2,
 	WACOM_21UX2,
 	CINTIQ,
 	CINTIQ,
 	WACOM_BEE,
 	WACOM_BEE,

+ 1 - 12
drivers/input/touchscreen/88pm860x-ts.c

@@ -217,18 +217,7 @@ static struct platform_driver pm860x_touch_driver = {
 	.probe	= pm860x_touch_probe,
 	.probe	= pm860x_touch_probe,
 	.remove	= __devexit_p(pm860x_touch_remove),
 	.remove	= __devexit_p(pm860x_touch_remove),
 };
 };
-
-static int __init pm860x_touch_init(void)
-{
-	return platform_driver_register(&pm860x_touch_driver);
-}
-module_init(pm860x_touch_init);
-
-static void __exit pm860x_touch_exit(void)
-{
-	platform_driver_unregister(&pm860x_touch_driver);
-}
-module_exit(pm860x_touch_exit);
+module_platform_driver(pm860x_touch_driver);
 
 
 MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
 MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");

+ 41 - 0
drivers/input/touchscreen/Kconfig

@@ -98,6 +98,19 @@ config TOUCHSCREEN_ATMEL_MXT
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called atmel_mxt_ts.
 	  module will be called atmel_mxt_ts.
 
 
+config TOUCHSCREEN_AUO_PIXCIR
+	tristate "AUO in-cell touchscreen using Pixcir ICs"
+	depends on I2C
+	depends on GPIOLIB
+	help
+	  Say Y here if you have a AUO display with in-cell touchscreen
+	  using Pixcir ICs.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called auo-pixcir-ts.
+
 config TOUCHSCREEN_BITSY
 config TOUCHSCREEN_BITSY
 	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
 	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
 	depends on SA1100_BITSY
 	depends on SA1100_BITSY
@@ -177,6 +190,16 @@ config TOUCHSCREEN_EETI
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called eeti_ts.
 	  module will be called eeti_ts.
 
 
+config TOUCHSCREEN_EGALAX
+	tristate "EETI eGalax multi-touch panel support"
+	depends on I2C
+	help
+	  Say Y here to enable support for I2C connected EETI
+	  eGalax multi-touch panels.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called egalax_ts.
+
 config TOUCHSCREEN_FUJITSU
 config TOUCHSCREEN_FUJITSU
 	tristate "Fujitsu serial touchscreen"
 	tristate "Fujitsu serial touchscreen"
 	select SERIO
 	select SERIO
@@ -435,6 +458,18 @@ config TOUCHSCREEN_UCB1400
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_ts.
 	  module will be called ucb1400_ts.
 
 
+config TOUCHSCREEN_PIXCIR
+	tristate "PIXCIR I2C touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a pixcir i2c touchscreen
+	  controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pixcir_i2c_ts.
+
 config TOUCHSCREEN_WM831X
 config TOUCHSCREEN_WM831X
 	tristate "Support for WM831x touchscreen controllers"
 	tristate "Support for WM831x touchscreen controllers"
 	depends on MFD_WM831X
 	depends on MFD_WM831X
@@ -541,6 +576,7 @@ config TOUCHSCREEN_USB_COMPOSITE
 	  - GoTop Super_Q2/GogoPen/PenPower tablets
 	  - GoTop Super_Q2/GogoPen/PenPower tablets
 	  - JASTEC USB Touch Controller/DigiTech DTR-02U
 	  - JASTEC USB Touch Controller/DigiTech DTR-02U
 	  - Zytronic controllers
 	  - Zytronic controllers
+	  - Elo TouchSystems 2700 IntelliTouch
 
 
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  Have a look at <http://linux.chapter7.ch/touchkit/> for
 	  a usage description and the required user-space stuff.
 	  a usage description and the required user-space stuff.
@@ -620,6 +656,11 @@ config TOUCHSCREEN_USB_JASTEC
 	bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT
 	bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EXPERT
 	depends on TOUCHSCREEN_USB_COMPOSITE
 	depends on TOUCHSCREEN_USB_COMPOSITE
 
 
+config TOUCHSCREEN_USB_ELO
+	default y
+	bool "Elo TouchSystems 2700 IntelliTouch controller device support" if EXPERT
+	depends on TOUCHSCREEN_USB_COMPOSITE
+
 config TOUCHSCREEN_USB_E2I
 config TOUCHSCREEN_USB_E2I
 	default y
 	default y
 	bool "e2i Touchscreen controller (e.g. from Mimo 740)"
 	bool "e2i Touchscreen controller (e.g. from Mimo 740)"

+ 3 - 0
drivers/input/touchscreen/Makefile

@@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
+obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
 obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
+obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
@@ -39,6 +41,7 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
+obj-$(CONFIG_TOUCHSCREEN_PIXCIR)	+= pixcir_i2c_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o

+ 8 - 9
drivers/input/touchscreen/ad7877.c

@@ -488,10 +488,10 @@ static ssize_t ad7877_disable_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 	struct ad7877 *ts = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -518,10 +518,10 @@ static ssize_t ad7877_dac_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 	struct ad7877 *ts = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -548,10 +548,10 @@ static ssize_t ad7877_gpio3_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 	struct ad7877 *ts = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -579,10 +579,10 @@ static ssize_t ad7877_gpio4_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct ad7877 *ts = dev_get_drvdata(dev);
 	struct ad7877 *ts = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 
@@ -853,7 +853,6 @@ static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
 static struct spi_driver ad7877_driver = {
 static struct spi_driver ad7877_driver = {
 	.driver = {
 	.driver = {
 		.name	= "ad7877",
 		.name	= "ad7877",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
 		.pm	= &ad7877_pm,
 		.pm	= &ad7877_pm,
 	},
 	},

+ 3 - 28
drivers/input/touchscreen/ad7879-i2c.c

@@ -16,30 +16,6 @@
 
 
 #define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
 #define AD7879_DEVID		0x79	/* AD7879-1/AD7889-1 */
 
 
-#ifdef CONFIG_PM_SLEEP
-static int ad7879_i2c_suspend(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7879 *ts = i2c_get_clientdata(client);
-
-	ad7879_suspend(ts);
-
-	return 0;
-}
-
-static int ad7879_i2c_resume(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ad7879 *ts = i2c_get_clientdata(client);
-
-	ad7879_resume(ts);
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume);
-
 /* All registers are word-sized.
 /* All registers are word-sized.
  * AD7879 uses a high-byte first convention.
  * AD7879 uses a high-byte first convention.
  */
  */
@@ -47,7 +23,7 @@ static int ad7879_i2c_read(struct device *dev, u8 reg)
 {
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_client *client = to_i2c_client(dev);
 
 
-	return swab16(i2c_smbus_read_word_data(client, reg));
+	return i2c_smbus_read_word_swapped(client, reg);
 }
 }
 
 
 static int ad7879_i2c_multi_read(struct device *dev,
 static int ad7879_i2c_multi_read(struct device *dev,
@@ -68,7 +44,7 @@ static int ad7879_i2c_write(struct device *dev, u8 reg, u16 val)
 {
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct i2c_client *client = to_i2c_client(dev);
 
 
-	return i2c_smbus_write_word_data(client, reg, swab16(val));
+	return i2c_smbus_write_word_swapped(client, reg, val);
 }
 }
 
 
 static const struct ad7879_bus_ops ad7879_i2c_bus_ops = {
 static const struct ad7879_bus_ops ad7879_i2c_bus_ops = {
@@ -119,7 +95,7 @@ static struct i2c_driver ad7879_i2c_driver = {
 	.driver = {
 	.driver = {
 		.name	= "ad7879",
 		.name	= "ad7879",
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
-		.pm	= &ad7879_i2c_pm,
+		.pm	= &ad7879_pm_ops,
 	},
 	},
 	.probe		= ad7879_i2c_probe,
 	.probe		= ad7879_i2c_probe,
 	.remove		= __devexit_p(ad7879_i2c_remove),
 	.remove		= __devexit_p(ad7879_i2c_remove),
@@ -141,4 +117,3 @@ module_exit(ad7879_i2c_exit);
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver");
 MODULE_DESCRIPTION("AD7879(-1) touchscreen I2C bus driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("i2c:ad7879");

+ 1 - 26
drivers/input/touchscreen/ad7879-spi.c

@@ -22,30 +22,6 @@
 #define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
 #define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
 #define AD7879_READCMD(reg)  (AD7879_CMD(reg) | AD7879_CMD_READ)
 #define AD7879_READCMD(reg)  (AD7879_CMD(reg) | AD7879_CMD_READ)
 
 
-#ifdef CONFIG_PM_SLEEP
-static int ad7879_spi_suspend(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	struct ad7879 *ts = spi_get_drvdata(spi);
-
-	ad7879_suspend(ts);
-
-	return 0;
-}
-
-static int ad7879_spi_resume(struct device *dev)
-{
-	struct spi_device *spi = to_spi_device(dev);
-	struct ad7879 *ts = spi_get_drvdata(spi);
-
-	ad7879_resume(ts);
-
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume);
-
 /*
 /*
  * ad7879_read/write are only used for initial setup and for sysfs controls.
  * ad7879_read/write are only used for initial setup and for sysfs controls.
  * The main traffic is done in ad7879_collect().
  * The main traffic is done in ad7879_collect().
@@ -174,9 +150,8 @@ static int __devexit ad7879_spi_remove(struct spi_device *spi)
 static struct spi_driver ad7879_spi_driver = {
 static struct spi_driver ad7879_spi_driver = {
 	.driver = {
 	.driver = {
 		.name	= "ad7879",
 		.name	= "ad7879",
-		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 		.owner	= THIS_MODULE,
-		.pm	= &ad7879_spi_pm,
+		.pm	= &ad7879_pm_ops,
 	},
 	},
 	.probe		= ad7879_spi_probe,
 	.probe		= ad7879_spi_probe,
 	.remove		= __devexit_p(ad7879_spi_remove),
 	.remove		= __devexit_p(ad7879_spi_remove),

+ 17 - 6
drivers/input/touchscreen/ad7879.c

@@ -281,8 +281,11 @@ static void ad7879_close(struct input_dev* input)
 		__ad7879_disable(ts);
 		__ad7879_disable(ts);
 }
 }
 
 
-void ad7879_suspend(struct ad7879 *ts)
+#ifdef CONFIG_PM_SLEEP
+static int ad7879_suspend(struct device *dev)
 {
 {
+	struct ad7879 *ts = dev_get_drvdata(dev);
+
 	mutex_lock(&ts->input->mutex);
 	mutex_lock(&ts->input->mutex);
 
 
 	if (!ts->suspended && !ts->disabled && ts->input->users)
 	if (!ts->suspended && !ts->disabled && ts->input->users)
@@ -291,11 +294,14 @@ void ad7879_suspend(struct ad7879 *ts)
 	ts->suspended = true;
 	ts->suspended = true;
 
 
 	mutex_unlock(&ts->input->mutex);
 	mutex_unlock(&ts->input->mutex);
+
+	return 0;
 }
 }
-EXPORT_SYMBOL(ad7879_suspend);
 
 
-void ad7879_resume(struct ad7879 *ts)
+static int ad7879_resume(struct device *dev)
 {
 {
+	struct ad7879 *ts = dev_get_drvdata(dev);
+
 	mutex_lock(&ts->input->mutex);
 	mutex_lock(&ts->input->mutex);
 
 
 	if (ts->suspended && !ts->disabled && ts->input->users)
 	if (ts->suspended && !ts->disabled && ts->input->users)
@@ -304,8 +310,13 @@ void ad7879_resume(struct ad7879 *ts)
 	ts->suspended = false;
 	ts->suspended = false;
 
 
 	mutex_unlock(&ts->input->mutex);
 	mutex_unlock(&ts->input->mutex);
+
+	return 0;
 }
 }
-EXPORT_SYMBOL(ad7879_resume);
+#endif
+
+SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume);
+EXPORT_SYMBOL(ad7879_pm_ops);
 
 
 static void ad7879_toggle(struct ad7879 *ts, bool disable)
 static void ad7879_toggle(struct ad7879 *ts, bool disable)
 {
 {
@@ -340,10 +351,10 @@ static ssize_t ad7879_disable_store(struct device *dev,
 				     const char *buf, size_t count)
 				     const char *buf, size_t count)
 {
 {
 	struct ad7879 *ts = dev_get_drvdata(dev);
 	struct ad7879 *ts = dev_get_drvdata(dev);
-	unsigned long val;
+	unsigned int val;
 	int error;
 	int error;
 
 
-	error = strict_strtoul(buf, 10, &val);
+	error = kstrtouint(buf, 10, &val);
 	if (error)
 	if (error)
 		return error;
 		return error;
 
 

Some files were not shown because too many files changed in this diff