Commit 3df7d8a6 authored by Ben Hutchings's avatar Ben Hutchings

Input: add support for Cypress PS/2 Trackpads (Closes: #703607), thanks to Apollon Oikonomopoulos

svn path=/dists/sid/linux/; revision=19952
parent d3d3caa0
linux (3.2.41-3) UNRELEASED; urgency=low
* Input: MT: add tracking and frame synchronisation to core
* Input: add support for Cypress PS/2 Trackpads (Closes: #703607),
thanks to Apollon Oikonomopoulos
-- Ben Hutchings <ben@decadent.org.uk> Wed, 27 Mar 2013 14:10:40 +0000
linux (3.2.41-2) unstable; urgency=low
* [ia64] udeb: Remove efi-modules package; make kernel-image provide
......
From: Henrik Rydberg <rydberg@euromail.se>
Date: Sat, 11 Aug 2012 22:07:55 +0200
Subject: Input: MT - Add flags to input_mt_init_slots()
commit b4adbbefc2099476a4f1020041c99f52cf3cd67d upstream.
Preparing to move more repeated code into the mt core, add a flags
argument to the input_mt_slots_init() function.
Reviewed-and-tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Tested-by: Ping Cheng <pingc@wacom.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
[bwh: Backported to wheezy:
- Introduce struct input_mt and use container_of() to find it from
input_dev::mt
- Rename input_mt_init_slot() to input_mt_init_slot_flags() and add a
backward-compatible wrapper]
[Apollon Oikonomopoulos: fix slot initialization in input_mt_init_slots_flags]
---
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -14,6 +14,9 @@
#define TRKID_SGN ((TRKID_MAX + 1) >> 1)
+#define input_dev_to_mt(dev) \
+ ((dev)->mt ? container_of((dev)->mt, struct input_mt, slots[0]) : NULL)
+
/**
* input_mt_init_slots() - initialize MT input slots
* @dev: input device supporting MT events and finger tracking
@@ -25,8 +28,10 @@
* May be called repeatedly. Returns -EINVAL if attempting to
* reinitialize with a different number of slots.
*/
-int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
+int input_mt_init_slots_flags(struct input_dev *dev, unsigned int num_slots,
+ unsigned int flags)
{
+ struct input_mt *mt;
int i;
if (!num_slots)
@@ -34,21 +39,29 @@ int input_mt_init_slots(struct input_dev
if (dev->mt)
return dev->mtsize != num_slots ? -EINVAL : 0;
- dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
- if (!dev->mt)
+ mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
+ if (!mt)
return -ENOMEM;
dev->mtsize = num_slots;
+ mt->flags = flags;
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
input_set_events_per_packet(dev, 6 * num_slots);
/* Mark slots as 'unused' */
for (i = 0; i < num_slots; i++)
- input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
+ input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
+ dev->mt = &mt->slots[0];
return 0;
}
+EXPORT_SYMBOL(input_mt_init_slots_flags);
+
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
+{
+ return input_mt_init_slots_flags(dev, num_slots, 0);
+}
EXPORT_SYMBOL(input_mt_init_slots);
/**
@@ -60,7 +73,7 @@ EXPORT_SYMBOL(input_mt_init_slots);
*/
void input_mt_destroy_slots(struct input_dev *dev)
{
- kfree(dev->mt);
+ kfree(input_dev_to_mt(dev));
dev->mt = NULL;
dev->mtsize = 0;
dev->slot = 0;
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -23,6 +23,16 @@ struct input_mt_slot {
int abs[ABS_MT_LAST - ABS_MT_FIRST + 1];
};
+/**
+ * struct input_mt - state of tracked contacts
+ * @flags: input_mt operation flags
+ * @slots: array of slots holding current values of tracked contacts
+ */
+struct input_mt {
+ unsigned int flags;
+ struct input_mt_slot slots[];
+};
+
static inline void input_mt_set_value(struct input_mt_slot *slot,
unsigned code, int value)
{
@@ -36,6 +46,8 @@ static inline int input_mt_get_value(con
}
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
+int input_mt_init_slots_flags(struct input_dev *dev, unsigned int num_slots,
+ unsigned int flags);
void input_mt_destroy_slots(struct input_dev *dev);
static inline int input_mt_new_trkid(struct input_dev *dev)
From: Henrik Rydberg <rydberg@euromail.se>
Date: Sun, 12 Aug 2012 20:47:05 +0200
Subject: Input: MT - Add in-kernel tracking
commit 7c1a87897c75139dec258eb03e1a24fb73385b73 upstream.
With the INPUT_MT_TRACK flag set, the function input_mt_assign_slots()
can be used to match a new set of contacts against the currently used
slots. The algorithm used is based on Lagrange relaxation, and performs
very well in practice; slower than mtdev for a few corner cases, but
faster in most commonly occuring cases.
Tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
---
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -50,7 +50,7 @@ int input_mt_init_slots_flags(struct inp
mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots) +
num_slots * sizeof(*mt->slot_frame), GFP_KERNEL);
if (!mt)
- return -ENOMEM;
+ goto err_mem;
dev->mtsize = num_slots;
mt->num_slots = num_slots;
@@ -81,6 +81,12 @@ int input_mt_init_slots_flags(struct inp
}
if (flags & INPUT_MT_DIRECT)
__set_bit(INPUT_PROP_DIRECT, dev->propbit);
+ if (flags & INPUT_MT_TRACK) {
+ unsigned int n2 = num_slots * num_slots;
+ mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
+ if (!mt->red)
+ goto err_mem;
+ }
/* Mark slots as 'unused' */
for (i = 0; i < num_slots; i++)
@@ -88,6 +94,9 @@ int input_mt_init_slots_flags(struct inp
dev->mt = &mt->slots[0];
return 0;
+err_mem:
+ kfree(mt);
+ return -ENOMEM;
}
EXPORT_SYMBOL(input_mt_init_slots_flags);
@@ -106,7 +115,11 @@ EXPORT_SYMBOL(input_mt_init_slots);
*/
void input_mt_destroy_slots(struct input_dev *dev)
{
- kfree(input_dev_to_mt(dev));
+ if (dev->mt) {
+ struct input_mt *mt = input_dev_to_mt(dev);
+ kfree(mt->red);
+ kfree(mt);
+ }
dev->mt = NULL;
dev->mtsize = 0;
dev->slot = 0;
@@ -253,3 +266,131 @@ void input_mt_sync_frame(struct input_de
mt->frame++;
}
EXPORT_SYMBOL(input_mt_sync_frame);
+
+static int adjust_dual(int *begin, int step, int *end, int eq)
+{
+ int f, *p, s, c;
+
+ if (begin == end)
+ return 0;
+
+ f = *begin;
+ p = begin + step;
+ s = p == end ? f + 1 : *p;
+
+ for (; p != end; p += step)
+ if (*p < f)
+ s = f, f = *p;
+ else if (*p < s)
+ s = *p;
+
+ c = (f + s + 1) / 2;
+ if (c == 0 || (c > 0 && !eq))
+ return 0;
+ if (s < 0)
+ c *= 2;
+
+ for (p = begin; p != end; p += step)
+ *p -= c;
+
+ return (c < s && s <= 0) || (f >= 0 && f < c);
+}
+
+static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
+{
+ int i, k, sum;
+
+ for (k = 0; k < nrc; k++) {
+ for (i = 0; i < nr; i++)
+ adjust_dual(w + i, nr, w + i + nrc, nr <= nc);
+ sum = 0;
+ for (i = 0; i < nrc; i += nr)
+ sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr);
+ if (!sum)
+ break;
+ }
+}
+
+static int input_mt_set_matrix(struct input_mt *mt,
+ const struct input_mt_pos *pos, int num_pos)
+{
+ const struct input_mt_pos *p;
+ struct input_mt_slot *s;
+ int *w = mt->red;
+ int x, y;
+
+ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+ if (!input_mt_is_active(s))
+ continue;
+ x = input_mt_get_value(s, ABS_MT_POSITION_X);
+ y = input_mt_get_value(s, ABS_MT_POSITION_Y);
+ for (p = pos; p != pos + num_pos; p++) {
+ int dx = x - p->x, dy = y - p->y;
+ *w++ = dx * dx + dy * dy;
+ }
+ }
+
+ return w - mt->red;
+}
+
+static void input_mt_set_slots(struct input_mt *mt,
+ int *slots, int num_pos)
+{
+ struct input_mt_slot *s;
+ int *w = mt->red, *p;
+
+ for (p = slots; p != slots + num_pos; p++)
+ *p = -1;
+
+ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+ if (!input_mt_is_active(s))
+ continue;
+ for (p = slots; p != slots + num_pos; p++)
+ if (*w++ < 0)
+ *p = s - mt->slots;
+ }
+
+ for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+ if (input_mt_is_active(s))
+ continue;
+ for (p = slots; p != slots + num_pos; p++)
+ if (*p < 0) {
+ *p = s - mt->slots;
+ break;
+ }
+ }
+}
+
+/**
+ * input_mt_assign_slots() - perform a best-match assignment
+ * @dev: input device with allocated MT slots
+ * @slots: the slot assignment to be filled
+ * @pos: the position array to match
+ * @num_pos: number of positions
+ *
+ * Performs a best match against the current contacts and returns
+ * the slot assignment list. New contacts are assigned to unused
+ * slots.
+ *
+ * Returns zero on success, or negative error in case of failure.
+ */
+int input_mt_assign_slots(struct input_dev *dev, int *slots,
+ const struct input_mt_pos *pos, int num_pos)
+{
+ struct input_mt *mt = input_dev_to_mt(dev);
+ int nrc;
+
+ if (!mt || !mt->red)
+ return -ENXIO;
+ if (num_pos > mt->num_slots)
+ return -EINVAL;
+ if (num_pos < 1)
+ return 0;
+
+ nrc = input_mt_set_matrix(mt, pos, num_pos);
+ find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc);
+ input_mt_set_slots(mt, slots, num_pos);
+
+ return 0;
+}
+EXPORT_SYMBOL(input_mt_assign_slots);
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -18,6 +18,8 @@
#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */
#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */
#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */
+#define INPUT_MT_TRACK 0x0008 /* use in-kernel tracking */
+
/**
* struct input_mt_slot - represents the state of an input MT slot
* @abs: holds current values of ABS_MT axes for this slot
@@ -39,6 +41,7 @@ struct input_mt {
unsigned int flags;
unsigned int frame;
unsigned int *slot_frame;
+ int *red;
struct input_mt_slot slots[];
};
@@ -54,6 +57,11 @@ static inline int input_mt_get_value(con
return slot->abs[code - ABS_MT_FIRST];
}
+static inline bool input_mt_is_active(const struct input_mt_slot *slot)
+{
+ return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
+}
+
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots);
int input_mt_init_slots_flags(struct input_dev *dev, unsigned int num_slots,
unsigned int flags);
@@ -83,4 +91,16 @@ void input_mt_report_pointer_emulation(s
void input_mt_sync_frame(struct input_dev *dev);
+/**
+ * struct input_mt_pos - contact position
+ * @x: horizontal coordinate
+ * @y: vertical coordinate
+ */
+struct input_mt_pos {
+ s16 x, y;
+};
+
+int input_mt_assign_slots(struct input_dev *dev, int *slots,
+ const struct input_mt_pos *pos, int num_pos);
+
#endif
From: Henrik Rydberg <rydberg@euromail.se>
Date: Wed, 22 Aug 2012 20:43:22 +0200
Subject: Input: MT - Handle frame synchronization in core
commit 55e49089f4589908eb688742d2d7eff33b74ac78 upstream.
Most MT drivers perform the same actions on frame synchronization.
Some actions, like dropping unseen contacts, are also unnecessarily
complex. Collect common frame synchronization tasks in a new function,
input_mt_sync_frame(). Depending on the flags set, it drops unseen
contacts and performs pointer emulation.
With init flags and frame synchronization in place, most MT drivers
can be simplified. First out are the bcm5974 and hid-multitouch
drivers, following this patch.
Reviewed-and-tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Tested-by: Ping Cheng <pingc@wacom.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
[bwh: Backported to wheezy:
- Add a separate array to track last frame each slot was used]
---
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -17,6 +17,14 @@
#define input_dev_to_mt(dev) \
((dev)->mt ? container_of((dev)->mt, struct input_mt, slots[0]) : NULL)
+static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
+{
+ if (dev->absinfo && test_bit(src, dev->absbit)) {
+ dev->absinfo[dst] = dev->absinfo[src];
+ dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
+ }
+}
+
/**
* input_mt_init_slots() - initialize MT input slots
* @dev: input device supporting MT events and finger tracking
@@ -39,16 +47,41 @@ int input_mt_init_slots_flags(struct inp
if (dev->mt)
return dev->mtsize != num_slots ? -EINVAL : 0;
- mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
+ mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots) +
+ num_slots * sizeof(*mt->slot_frame), GFP_KERNEL);
if (!mt)
return -ENOMEM;
dev->mtsize = num_slots;
+ mt->num_slots = num_slots;
mt->flags = flags;
+ mt->slot_frame = (unsigned int *)&mt->slots[num_slots];
input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
input_set_events_per_packet(dev, 6 * num_slots);
+ if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
+ __set_bit(EV_KEY, dev->evbit);
+ __set_bit(BTN_TOUCH, dev->keybit);
+
+ copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
+ copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
+ copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
+ }
+ if (flags & INPUT_MT_POINTER) {
+ __set_bit(BTN_TOOL_FINGER, dev->keybit);
+ __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+ if (num_slots >= 3)
+ __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
+ if (num_slots >= 4)
+ __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+ if (num_slots >= 5)
+ __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+ __set_bit(INPUT_PROP_POINTER, dev->propbit);
+ }
+ if (flags & INPUT_MT_DIRECT)
+ __set_bit(INPUT_PROP_DIRECT, dev->propbit);
+
/* Mark slots as 'unused' */
for (i = 0; i < num_slots; i++)
input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
@@ -96,17 +129,23 @@ EXPORT_SYMBOL(input_mt_destroy_slots);
void input_mt_report_slot_state(struct input_dev *dev,
unsigned int tool_type, bool active)
{
- struct input_mt_slot *mt;
+ struct input_mt *mt = input_dev_to_mt(dev);
+ struct input_mt_slot *slot;
int id;
- if (!dev->mt || !active) {
+ if (!mt)
+ return;
+
+ slot = &mt->slots[dev->slot];
+ mt->slot_frame[dev->slot] = mt->frame;
+
+ if (!active) {
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
return;
}
- mt = &dev->mt[dev->slot];
- id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
- if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
+ id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
+ if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
id = input_mt_new_trkid(dev);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
@@ -183,3 +222,34 @@ void input_mt_report_pointer_emulation(s
}
}
EXPORT_SYMBOL(input_mt_report_pointer_emulation);
+
+/**
+ * input_mt_sync_frame() - synchronize mt frame
+ * @dev: input device with allocated MT slots
+ *
+ * Close the frame and prepare the internal state for a new one.
+ * Depending on the flags, marks unused slots as inactive and performs
+ * pointer emulation.
+ */
+void input_mt_sync_frame(struct input_dev *dev)
+{
+ struct input_mt *mt = input_dev_to_mt(dev);
+ unsigned int i;
+
+ if (!mt)
+ return;
+
+ if (mt->flags & INPUT_MT_DROP_UNUSED) {
+ for (i = 0; i < mt->num_slots; i++) {
+ if (mt->slot_frame[i] == mt->frame)
+ continue;
+ input_mt_slot(dev, i);
+ input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+ }
+ }
+
+ input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
+
+ mt->frame++;
+}
+EXPORT_SYMBOL(input_mt_sync_frame);
--- a/include/linux/input/mt.h
+++ b/include/linux/input/mt.h
@@ -15,6 +15,9 @@
#define TRKID_MAX 0xffff
+#define INPUT_MT_POINTER 0x0001 /* pointer device, e.g. trackpad */
+#define INPUT_MT_DIRECT 0x0002 /* direct device, e.g. touchscreen */
+#define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */
/**
* struct input_mt_slot - represents the state of an input MT slot
* @abs: holds current values of ABS_MT axes for this slot
@@ -25,11 +28,17 @@ struct input_mt_slot {
/**
* struct input_mt - state of tracked contacts
+ * @num_slots: number of MT slots the device uses
* @flags: input_mt operation flags
+ * @frame: increases every time input_mt_sync_frame() is called
+ * @slot_frame: last frame at which input_mt_report_slot_state() was called
* @slots: array of slots holding current values of tracked contacts
*/
struct input_mt {
+ int num_slots;
unsigned int flags;
+ unsigned int frame;
+ unsigned int *slot_frame;
struct input_mt_slot slots[];
};
@@ -72,4 +81,6 @@ void input_mt_report_slot_state(struct i
void input_mt_report_finger_count(struct input_dev *dev, int count);
void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count);
+void input_mt_sync_frame(struct input_dev *dev);
+
#endif
From: Kamal Mostafa <kamal@canonical.com>
Date: Thu, 21 Feb 2013 11:55:05 -0800
Subject: Input: cypress_ps2 - fix trackpadi found in Dell XPS12
commit 81bb5d31fbf3893a8e041c649dea704dd11d5272 upstream.
Avoid firmware glitch in Cypress PS/2 Trackpad firmware version 11
(as observed in Dell XPS12) which prevents driver from recognizing
the trackpad.
BugLink: http://launchpad.net/bugs/1103594
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Cc: Dudley Du <dudl@cypress.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/mouse/cypress_ps2.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c
index 1673dc6..f51765f 100644
--- a/drivers/input/mouse/cypress_ps2.c
+++ b/drivers/input/mouse/cypress_ps2.c
@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse)
cytp->fw_version = param[2] & FW_VERSION_MASX;
cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0;
+ /*
+ * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
+ * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
+ */
+ if (cytp->fw_version >= 11)
+ cytp->tp_metrics_supported = 0;
+
psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version);
psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n",
cytp->tp_metrics_supported);
@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width;
cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high;
+ if (!cytp->tp_metrics_supported)
+ return 0;
+
memset(param, 0, sizeof(param));
if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) {
/* Update trackpad parameters. */
@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
static int cypress_query_hardware(struct psmouse *psmouse)
{
- struct cytp_data *cytp = psmouse->private;
int ret;
ret = cypress_read_fw_version(psmouse);
if (ret)
return ret;
- if (cytp->tp_metrics_supported) {
- ret = cypress_read_tp_metrics(psmouse);
- if (ret)
- return ret;
- }
+ ret = cypress_read_tp_metrics(psmouse);
+ if (ret)
+ return ret;
return 0;
}
......@@ -639,3 +639,10 @@ bugfix/x86/drm-i915-bounds-check-execbuffer-relocation-count.patch
bugfix/x86/KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch
bugfix/x86/KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch
bugfix/all/KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch
# Input multitouch extensions from 3.7
features/all/input-mt/Input-MT-Add-flags-to-input_mt_init_slots.patch
features/all/input-mt/Input-MT-Handle-frame-synchronization-in-core.patch
features/all/input-mt/Input-MT-Add-in-kernel-tracking.patch
features/all/input-mt/Input-add-support-for-Cypress-PS-2-Trackpads.patch
features/all/input-mt/Input-cypress_ps2-fix-trackpadi-found-in-Dell-XPS12.patch
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment