@@ -372,6 +372,9 @@ struct mxt_data {
unsigned int t19_num_keys;
enum mxt_suspend_mode suspend_mode;
+
+ /* Indicates whether device is in suspend */
+ bool suspended;
};
struct mxt_vb2_buffer {
@@ -1150,10 +1153,10 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
mxt_proc_t42_messages(data, message);
} else if (report_id == data->T48_reportid) {
mxt_proc_t48_messages(data, message);
- } else if (!data->input_dev) {
+ } else if (!data->input_dev || data->suspended) {
/*
- * Do not report events if input device
- * is not yet registered.
+ * Do not report events if input device is not
+ * yet registered or returning from suspend
*/
mxt_dump_message(data, message);
} else if (report_id >= data->T9_reportid_min &&
@@ -3131,6 +3134,11 @@ static int mxt_load_fw(struct device *dev, const char *fn)
if (ret)
goto release_firmware;
+ if (data->suspended) {
+ enable_irq(data->irq);
+ data->suspended = false;
+ }
+
if (!data->in_bootloader) {
/* Change to the bootloader mode */
data->in_bootloader = true;
@@ -3302,8 +3310,27 @@ static void mxt_sysfs_remove(struct mxt_data *data)
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
}
+static void mxt_reset_slots(struct mxt_data *data)
+{
+ struct input_dev *input_dev = data->input_dev;
+ int id;
+
+ if (!input_dev)
+ return;
+
+ for (id = 0; id < data->num_touchids; id++) {
+ input_mt_slot(input_dev, id);
+ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
+ }
+
+ mxt_input_sync(data);
+}
+
static void mxt_start(struct mxt_data *data)
{
+ if (!data->suspended || data->in_bootloader)
+ return;
+
switch (data->suspend_mode) {
case MXT_SUSPEND_T9_CTRL:
mxt_soft_reset(data);
@@ -3316,16 +3343,29 @@ static void mxt_start(struct mxt_data *data)
case MXT_SUSPEND_DEEP_SLEEP:
default:
+ /*
+ * Discard any touch messages still in message buffer
+ * from before chip went to sleep
+ */
+ mxt_process_messages_until_invalid(data);
+
mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
/* Recalibrate since chip has been in deep sleep */
mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
+
+ mxt_acquire_irq(data);
break;
}
+
+ data->suspended = false;
}
static void mxt_stop(struct mxt_data *data)
{
+ if (data->suspended || data->in_bootloader)
+ return;
+
switch (data->suspend_mode) {
case MXT_SUSPEND_T9_CTRL:
/* Touch disable */
@@ -3335,9 +3375,15 @@ static void mxt_stop(struct mxt_data *data)
case MXT_SUSPEND_DEEP_SLEEP:
default:
+ disable_irq(data->irq);
+
mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
+
+ mxt_reset_slots(data);
break;
}
+
+ data->suspended = true;
}
static int mxt_input_open(struct input_dev *dev)