*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Copyright (C) 2011 Atmel Corporation
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright (C) 2011-2012 NVIDIA Corporation
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#endif
+#define CREATE_TRACE_POINTS
+#include <trace/events/nvevent.h>
/* Family ID */
#define MXT224_ID 0x80
#define MXT_VOLTAGE_DEFAULT 2700000
#define MXT_VOLTAGE_STEP 10000
-/* Defines for MXT_TOUCH_CTRL */
-#define MXT_TOUCH_DISABLE 0
-#define MXT_TOUCH_ENABLE 0x83
+/* Defines for Suspend/Resume */
+#define MXT_SUSPEND_STATIC 0
+#define MXT_SUSPEND_DYNAMIC 1
+#define MXT_T7_IDLEACQ_DISABLE 0
+#define MXT_T7_ACTVACQ_DISABLE 0
+#define MXT_T7_ACTV2IDLE_DISABLE 0
+#define MXT_T9_DISABLE 0
+#define MXT_T9_ENABLE 0x83
+#define MXT_T22_DISABLE 0
/* Define for MXT_GEN_COMMAND_T6 */
#define MXT_BOOT_VALUE 0xa5
#define RESUME_READS 100
+#define MXT_DEFAULT_PRESSURE 100
+
struct mxt_info {
u8 family_id;
u8 variant_id;
int pressure;
};
+/* This structure is used to save/restore values during suspend/resume */
+struct mxt_suspend {
+ u8 suspend_obj;
+ u8 suspend_reg;
+ u8 suspend_val;
+ u8 suspend_flags;
+ u8 restore_val;
+};
+
/* Each client has this additional data */
struct mxt_data {
struct i2c_client *client;
u8 slowscan_shad_actv2idle_timeout;
};
+static struct mxt_suspend mxt_save[] = {
+ {MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, MXT_T9_DISABLE, MXT_SUSPEND_DYNAMIC, 0},
+ {MXT_PROCG_NOISE_T22, MXT_NOISE_CTRL, MXT_T22_DISABLE, MXT_SUSPEND_DYNAMIC, 0},
+ {MXT_GEN_POWER_T7, MXT_POWER_IDLEACQINT, MXT_T7_IDLEACQ_DISABLE, MXT_SUSPEND_DYNAMIC, 0},
+ {MXT_GEN_POWER_T7, MXT_POWER_ACTVACQINT, MXT_T7_ACTVACQ_DISABLE, MXT_SUSPEND_DYNAMIC, 0},
+ {MXT_GEN_POWER_T7, MXT_POWER_ACTV2IDLETO, MXT_T7_ACTV2IDLE_DISABLE, MXT_SUSPEND_DYNAMIC, 0}
+};
+
#if defined(CONFIG_HAS_EARLYSUSPEND)
static void mxt_early_suspend(struct early_suspend *es);
static void mxt_early_resume(struct early_suspend *es);
if (status != MXT_RELEASE) {
input_report_abs(input_dev, ABS_X, finger[single_id].x);
input_report_abs(input_dev, ABS_Y, finger[single_id].y);
- input_report_abs(input_dev,
- ABS_PRESSURE, finger[single_id].pressure);
+ input_report_abs(input_dev, ABS_PRESSURE, finger[single_id].pressure);
}
input_sync(input_dev);
dev_dbg(dev, "[%d] released\n", id);
finger[id].status = MXT_RELEASE;
+ finger[id].pressure = 0;
mxt_input_report(data, id);
}
return;
area = message->message[4];
pressure = message->message[5];
+ if ((pressure <= 0) || (pressure > 255))
+ pressure = MXT_DEFAULT_PRESSURE;
+
dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
status & MXT_MOVE ? "moved" : "pressed",
x, y, area);
finger[id].area = area;
finger[id].pressure = pressure;
+ trace_nvevent_irq_data_submit("mxt_input_touchevent");
mxt_input_report(data, id);
}
int touchid;
u8 reportid;
+ trace_nvevent_irq_data_read_start_series("mxt_input_interrupt");
do {
+ trace_nvevent_irq_data_read_start_single("mxt_input_interrupt");
if (mxt_read_message(data, &message)) {
dev_err(dev, "Failed to read message\n");
goto end;
}
+ trace_nvevent_irq_data_read_finish_single(
+ "mxt_input_interrupt");
reportid = message.reportid;
} else if (reportid != MXT_RPTID_NOMSG)
mxt_dump_message(dev, &message);
} while (reportid != MXT_RPTID_NOMSG);
+ trace_nvevent_irq_data_read_finish_series("mxt_input_interrupt");
end:
return IRQ_HANDLED;
if ((ret == 1) || (ret == 2)) {
switch (fn) {
case SLOSCAN_DISABLE:
- data->actv_cycle_time = data->slowscan_shad_actv_cycle_time;
- data->idle_cycle_time = data->slowscan_shad_idle_cycle_time;
- data->actv2idle_timeout = data->slowscan_shad_actv2idle_timeout;
- data->slowscan_enabled = 0;
- mxt_set_power_cfg(data, 0);
+ if (data->slowscan_enabled) {
+ data->actv_cycle_time = data->slowscan_shad_actv_cycle_time;
+ data->idle_cycle_time = data->slowscan_shad_idle_cycle_time;
+ data->actv2idle_timeout = data->slowscan_shad_actv2idle_timeout;
+ data->slowscan_enabled = 0;
+ mxt_set_power_cfg(data, 0);
+ }
break;
case SLOSCAN_ENABLE:
- data->slowscan_shad_actv_cycle_time = data->actv_cycle_time;
- data->slowscan_shad_idle_cycle_time = data->idle_cycle_time;
- data->slowscan_shad_actv2idle_timeout = data->actv2idle_timeout;
- data->actv_cycle_time = data->slowscan_actv_cycle_time;
- data->idle_cycle_time = data->slowscan_idle_cycle_time;
- data->actv2idle_timeout = data->slowscan_actv2idle_timeout;
- data->slowscan_enabled = 1;
- mxt_set_power_cfg(data, 0);
+ if (!data->slowscan_enabled) {
+ data->slowscan_shad_actv_cycle_time = data->actv_cycle_time;
+ data->slowscan_shad_idle_cycle_time = data->idle_cycle_time;
+ data->slowscan_shad_actv2idle_timeout = data->actv2idle_timeout;
+ data->actv_cycle_time = data->slowscan_actv_cycle_time;
+ data->idle_cycle_time = data->slowscan_idle_cycle_time;
+ data->actv2idle_timeout = data->slowscan_actv2idle_timeout;
+ data->slowscan_enabled = 1;
+ mxt_set_power_cfg(data, 0);
+ }
break;
case SLOSCAN_SET_ACTVACQINT:
u8 data[256];
} i2c_block_transfer;
- struct mxt_data *mxt;
-
if (length > 256)
return -EINVAL;
static void mxt_start(struct mxt_data *data)
{
- int error;
+ int error = 0;
+ int cnt;
struct device *dev = &data->client->dev;
dev_info(dev, "mxt_start: is_stopped = %d\n", data->is_stopped);
return;
/* Touch enable */
- error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, MXT_TOUCH_ENABLE);
+ cnt = ARRAY_SIZE(mxt_save);
+ while (cnt--)
+ error |= mxt_write_object(data, mxt_save[cnt].suspend_obj,
+ mxt_save[cnt].suspend_reg,
+ mxt_save[cnt].restore_val);
if (!error)
dev_info(dev, "MXT started\n");
static void mxt_stop(struct mxt_data *data)
{
- int error;
+ int error = 0;
+ int i, cnt;
struct device *dev = &data->client->dev;
dev_info(dev, "mxt_stop: is_stopped = %d\n", data->is_stopped);
return;
/* Touch disable */
- error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, MXT_TOUCH_DISABLE);
+ cnt = ARRAY_SIZE(mxt_save);
+ for (i = 0; i < cnt; i++) {
+ if (mxt_save[i].suspend_flags == MXT_SUSPEND_DYNAMIC)
+ error |= mxt_read_object(data,
+ mxt_save[i].suspend_obj,
+ mxt_save[i].suspend_reg,
+ &mxt_save[i].restore_val);
+ error |= mxt_write_object(data, mxt_save[i].suspend_obj,
+ mxt_save[i].suspend_reg,
+ mxt_save[i].suspend_val);
+ }
if (!error)
dev_info(dev, "MXT suspended\n");
sysfs_bin_attr_init(&data->mem_access_attr);
data->mem_access_attr.attr.name = "mem_access";
- data->mem_access_attr.attr.mode = S_IRUGO | S_IWUGO;
+ data->mem_access_attr.attr.mode = S_IRUGO | S_IWUSR | S_IWGRP;
data->mem_access_attr.read = mxt_mem_access_read;
data->mem_access_attr.write = mxt_mem_access_write;
data->mem_access_attr.size = 65535;
.driver = {
.name = "atmel_mxt_ts",
.owner = THIS_MODULE,
-#if !defined(CONFIG_HAS_EARLYSUSPEND)
+#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
.pm = &mxt_pm_ops,
#endif
},