Input: synaptics - add support for Relative mode

Currently, the synaptics driver puts the device into Absolute mode.
As explained in the synaptics documentation section 3.2, in this mode,
the device sends a continuous stream of packets at the maximum rate
to the host when the user's fingers are near or on the pad or
pressing buttons, and continues streaming for 1 second afterwards.
These packets are even sent when there is no new information to report,
even when they are duplicates of the previous packet.

For embedded systems this is a bit much - it results in a huge
and uninterrupted stream of interrupts at high rate.

This patch adds support for Relative mode, which can be selected as
a new psmouse protocol. In this mode, the device does not send duplicate
packets and acts like a standard PS/2 mouse. However, synaptics-specific
functionality is still available, such as the ability to set the packet
rate, and rather than disabling gestures and taps at the hardware level
unconditionally, a 'synaptics_disable_gesture' sysfs attribute has
been added to allow control of this functionality.

This solves a long standing OLPC issue: synaptics hardware enables
tap to click by default (even in the default relative mode), but we
have found this to be inappropriate for young children and first
time computer users. Enabling the synaptics driver disables tap-to-click,
but we have previously been unable to use this because it also enables
Absolute mode, which is too "spammy" for our desires and actually
overloads our EC with its continuous stream of packets. Now we can enable
the synaptics driver, disabling tap to click while retaining the less
noisy Relative mode.

Signed-off-by: Daniel Drake <dsd@laptop.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index 622aea8dd..fd26ccc 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -100,6 +100,7 @@
 #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_IS_SYNAPTICS(i)		((((i) >> 8) & 0xff) == 0x47)
+#define SYN_ID_DISGEST_SUPPORTED(i)	(SYN_ID_MAJOR(i) >= 4)
 
 /* synaptics special commands */
 #define SYN_PS_SET_MODE2		0x14
@@ -159,6 +160,9 @@
 	unsigned char mode;			/* current mode byte */
 	int scroll;
 
+	bool absolute_mode;			/* run in Absolute mode */
+	bool disable_gesture;			/* disable gestures */
+
 	struct serio *pt_port;			/* Pass-through serio port */
 
 	struct synaptics_mt_state mt_state;	/* Current mt finger state */
@@ -175,6 +179,7 @@
 void synaptics_module_init(void);
 int synaptics_detect(struct psmouse *psmouse, bool set_properties);
 int synaptics_init(struct psmouse *psmouse);
+int synaptics_init_relative(struct psmouse *psmouse);
 void synaptics_reset(struct psmouse *psmouse);
 bool synaptics_supported(void);