diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d5b390f..0215c7c 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -45,6 +45,7 @@
 #define YMIN_NOMINAL 1408
 #define YMAX_NOMINAL 4448
 
+static bool cr48_profile_sensor;
 
 /*****************************************************************************
  *	Stuff we need even when we do not want native Synaptics support
@@ -1003,6 +1004,75 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
 	priv->agm_pending = false;
 }
 
+static int synaptics_distsq(const struct input_mt_slot *slot,
+			    const struct synaptics_hw_state *hw)
+{
+	int slot_x = input_mt_get_value(slot, ABS_MT_POSITION_X);
+	int slot_y = input_mt_get_value(slot, ABS_MT_POSITION_Y);
+	int dx = hw->x - slot_x;
+	int dy = synaptics_invert_y(hw->y) - slot_y;
+	return dx * dx + dy * dy;
+}
+
+static bool synaptics_is_sgm_slot(const struct input_mt_slot *slot,
+				  const struct synaptics_hw_state *sgm,
+				  const struct synaptics_hw_state *agm)
+{
+	return (synaptics_distsq(slot, sgm) < synaptics_distsq(slot, agm));
+}
+
+static int synaptics_get_sgm_slot(const struct input_mt_slot *slots,
+				  const struct synaptics_hw_state *sgm)
+{
+	int distsq_slot0 = synaptics_distsq(&slots[0], sgm);
+	int distsq_slot1 = synaptics_distsq(&slots[1], sgm);
+	return (distsq_slot0 < distsq_slot1 ? 0 : 1);
+}
+
+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 *agm = &priv->agm;
+	struct synaptics_mt_state mt_state;
+
+	/* Initialize using current mt_state (as updated by last agm) */
+	mt_state = agm->mt_state;
+
+	if (num_fingers >= 2) {
+		/* Get previous sgm slot if exists */
+		int sgm_slot = (mt_state.count != 0) ? mt_state.sgm : 0;
+		if (mt_state.count == 1) {
+			const struct input_mt_slot *mt = &dev->mt[sgm_slot];
+			if (!synaptics_is_sgm_slot(mt, sgm, agm))
+				sgm_slot = 1 - sgm_slot;
+		}
+		synaptics_report_slot(dev, sgm_slot, sgm);
+		synaptics_report_slot(dev, 1 - sgm_slot, agm);
+		synaptics_mt_state_set(&mt_state, num_fingers,
+				       sgm_slot, 1 - sgm_slot);
+	} else if (num_fingers == 1) {
+		int sgm_slot = (mt_state.count != 0) ? mt_state.sgm : 0;
+		if (mt_state.count >= 2)
+			sgm_slot = synaptics_get_sgm_slot(dev->mt, sgm);
+		synaptics_report_slot(dev, sgm_slot, sgm);
+		synaptics_report_slot(dev, 1 - sgm_slot, NULL);
+		synaptics_mt_state_set(&mt_state, 1, sgm_slot, -1);
+	} else {
+		synaptics_report_slot(dev, 0, NULL);
+		synaptics_report_slot(dev, 1, NULL);
+		synaptics_mt_state_set(&mt_state, 0, -1, -1);
+	}
+	/* Store updated mt_state */
+	priv->mt_state = agm->mt_state = mt_state;
+	/* Send the number of fingers reported by touchpad itself. */
+	input_mt_report_finger_count(dev, mt_state.count);
+	synaptics_report_buttons(psmouse, sgm);
+	input_sync(dev);
+}
+
 /*
  *  called for each full received packet from the touchpad
  */
@@ -1066,6 +1136,12 @@ 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);
@@ -1227,6 +1303,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 					ABS_MT_POSITION_Y);
 	}
 
+	if (cr48_profile_sensor)
+		input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
 	if (SYN_CAP_PALMDETECT(priv->capabilities))
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
 
@@ -1422,10 +1501,24 @@ static const struct dmi_system_id __initconst olpc_dmi_table[] = {
 	{ }
 };
 
+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)
