|
@@ -117,6 +117,9 @@ void synaptics_reset(struct psmouse *psmouse)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
|
|
|
+
|
|
|
+static bool cr48_profile_sensor;
|
|
|
+
|
|
|
struct min_max_quirk {
|
|
|
const char * const *pnp_ids;
|
|
|
int x_min, x_max, y_min, y_max;
|
|
@@ -1151,6 +1154,42 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
|
|
|
priv->agm_pending = false;
|
|
|
}
|
|
|
|
|
|
+static void synaptics_profile_sensor_process(struct psmouse *psmouse,
|
|
|
+ struct synaptics_hw_state *sgm,
|
|
|
+ int num_fingers)
|
|
|
+{
|
|
|
+ struct input_dev *dev = psmouse->dev;
|
|
|
+ struct synaptics_data *priv = psmouse->private;
|
|
|
+ struct synaptics_hw_state *hw[2] = { sgm, &priv->agm };
|
|
|
+ struct input_mt_pos pos[2];
|
|
|
+ int slot[2], nsemi, i;
|
|
|
+
|
|
|
+ nsemi = clamp_val(num_fingers, 0, 2);
|
|
|
+
|
|
|
+ for (i = 0; i < nsemi; i++) {
|
|
|
+ pos[i].x = hw[i]->x;
|
|
|
+ pos[i].y = synaptics_invert_y(hw[i]->y);
|
|
|
+ }
|
|
|
+
|
|
|
+ input_mt_assign_slots(dev, slot, pos, nsemi);
|
|
|
+
|
|
|
+ for (i = 0; i < nsemi; i++) {
|
|
|
+ input_mt_slot(dev, slot[i]);
|
|
|
+ input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
|
|
|
+ input_report_abs(dev, ABS_MT_POSITION_X, pos[i].x);
|
|
|
+ input_report_abs(dev, ABS_MT_POSITION_Y, pos[i].y);
|
|
|
+ input_report_abs(dev, ABS_MT_PRESSURE, hw[i]->z);
|
|
|
+ }
|
|
|
+
|
|
|
+ input_mt_drop_unused(dev);
|
|
|
+ input_mt_report_pointer_emulation(dev, false);
|
|
|
+ input_mt_report_finger_count(dev, num_fingers);
|
|
|
+
|
|
|
+ synaptics_report_buttons(psmouse, sgm);
|
|
|
+
|
|
|
+ input_sync(dev);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* called for each full received packet from the touchpad
|
|
|
*/
|
|
@@ -1214,6 +1253,11 @@ static void synaptics_process_packet(struct psmouse *psmouse)
|
|
|
finger_width = 0;
|
|
|
}
|
|
|
|
|
|
+ if (cr48_profile_sensor) {
|
|
|
+ synaptics_profile_sensor_process(psmouse, &hw, num_fingers);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
|
|
|
synaptics_report_semi_mt_data(dev, &hw, &priv->agm,
|
|
|
num_fingers);
|
|
@@ -1359,6 +1403,9 @@ static void set_input_params(struct psmouse *psmouse,
|
|
|
set_abs_position_params(dev, priv, ABS_X, ABS_Y);
|
|
|
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
|
|
|
|
|
|
+ if (cr48_profile_sensor)
|
|
|
+ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
|
|
|
+
|
|
|
if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
|
|
|
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
|
|
|
ABS_MT_POSITION_Y);
|
|
@@ -1372,9 +1419,14 @@ static void set_input_params(struct psmouse *psmouse,
|
|
|
} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
|
|
|
set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
|
|
|
ABS_MT_POSITION_Y);
|
|
|
- /* Non-image sensors with AGM use semi-mt */
|
|
|
+ /*
|
|
|
+ * Profile sensor in CR-48 tracks contacts reasonably well,
|
|
|
+ * other non-image sensors with AGM use semi-mt.
|
|
|
+ */
|
|
|
input_mt_init_slots(dev, 2,
|
|
|
- INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
|
|
|
+ INPUT_MT_POINTER |
|
|
|
+ (cr48_profile_sensor ?
|
|
|
+ INPUT_MT_TRACK : INPUT_MT_SEMI_MT));
|
|
|
}
|
|
|
|
|
|
if (SYN_CAP_PALMDETECT(priv->capabilities))
|
|
@@ -1576,10 +1628,24 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = {
|
|
|
{ }
|
|
|
};
|
|
|
|
|
|
+static const struct dmi_system_id __initconst cr48_dmi_table[] = {
|
|
|
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
|
|
+ {
|
|
|
+ /* Cr-48 Chromebook (Codename Mario) */
|
|
|
+ .matches = {
|
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "IEC"),
|
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
|
|
|
+ },
|
|
|
+ },
|
|
|
+#endif
|
|
|
+ { }
|
|
|
+};
|
|
|
+
|
|
|
void __init synaptics_module_init(void)
|
|
|
{
|
|
|
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
|
|
|
broken_olpc_ec = dmi_check_system(olpc_dmi_table);
|
|
|
+ cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
|
|
|
}
|
|
|
|
|
|
static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
|