]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/input/touchscreen/atmel_mxt_ts.c
input: touch: atmel_mxt_ts: Add Ftrace logging.
[linux-2.6.git] / drivers / input / touchscreen / atmel_mxt_ts.c
index c9527efaffda07cb02d494df61ae9d347c2d1fe0..6721a1fd2456d16f19d1d0b27445e622629a2d11 100644 (file)
@@ -3,7 +3,7 @@
  *
  * 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
@@ -25,6 +25,8 @@
 #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;
@@ -280,6 +290,15 @@ struct mxt_finger {
        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;
@@ -314,6 +333,14 @@ struct mxt_data {
        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);
@@ -634,8 +661,7 @@ static void mxt_input_report(struct mxt_data *data, int single_id)
        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);
@@ -658,6 +684,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
                        dev_dbg(dev, "[%d] released\n", id);
 
                        finger[id].status = MXT_RELEASE;
+                       finger[id].pressure = 0;
                        mxt_input_report(data, id);
                }
                return;
@@ -677,6 +704,9 @@ static void mxt_input_touchevent(struct mxt_data *data,
        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);
@@ -688,6 +718,7 @@ static void mxt_input_touchevent(struct mxt_data *data,
        finger[id].area = area;
        finger[id].pressure = pressure;
 
+       trace_nvevent_irq_data_submit("mxt_input_touchevent");
        mxt_input_report(data, id);
 }
 
@@ -700,11 +731,15 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_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;
 
@@ -723,6 +758,7 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
                } 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;
@@ -1395,22 +1431,26 @@ static ssize_t mxt_slowscan_store(struct device *dev,
        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:
@@ -1459,8 +1499,6 @@ int mxt_write_block(struct i2c_client *client, u16 addr, u16 length, u8 *value)
                u8  data[256];
        } i2c_block_transfer;
 
-       struct mxt_data *mxt;
-
        if (length > 256)
                return -EINVAL;
 
@@ -1522,7 +1560,8 @@ static const struct attribute_group mxt_attr_group = {
 
 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);
@@ -1530,7 +1569,11 @@ static void mxt_start(struct mxt_data *data)
                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");
@@ -1540,7 +1583,8 @@ static void mxt_start(struct mxt_data *data)
 
 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);
@@ -1548,7 +1592,17 @@ static void mxt_stop(struct mxt_data *data)
                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");
@@ -1670,7 +1724,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
 
        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;
@@ -1793,7 +1847,7 @@ static struct i2c_driver mxt_driver = {
        .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
        },