input: touchscreen: synaptics: detect and notify out of idle
Yogish Kulkarni [Thu, 20 Jun 2013 11:21:43 +0000 (16:21 +0530)]
Detect no spi interrupt for 50ms as idle. On first interrupt after
idle report miscellaneous input event MSC_ACTIVITY. This event will
serve as early notification for actual input event and will allow
cpu frequency governor to boost CPU clk early.

Bug 1307520

Change-Id: I9dfa037303cb303da120716911e5c1ab375fc222
Signed-off-by: Yogish Kulkarni <yogishk@nvidia.com>
Reviewed-on: http://git-master/r/240592
(cherry picked from commit 2da59642dd69ae2482e8d088d8d99cf7fa18bf7e)
Reviewed-on: http://git-master/r/328304
Reviewed-by: Vikas Jain <vjain@nvidia.com>
Tested-by: Vikas Jain <vjain@nvidia.com>
Reviewed-by: Robert Collins <rcollins@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/input/touchscreen/rmi4/rmi_f11.c
drivers/input/touchscreen/rmi4/rmi_spi.c
include/linux/rmi.h

index 6717b84..cac6365 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2011,2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
+ * Copyright (C) 2013, NVIDIA Corporation.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
@@ -2493,6 +2494,9 @@ static int rmi_f11_register_devices(struct rmi_function_dev *fn_dev)
                set_bit(EV_SYN, input_dev->evbit);
                set_bit(EV_ABS, input_dev->evbit);
                input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
+#if NV_NOTIFY_OUT_OF_IDLE
+               input_set_capability(input_dev, EV_MSC, MSC_ACTIVITY);
+#endif
 
                f11_set_abs_params(fn_dev, i);
 
@@ -2646,6 +2650,22 @@ int rmi_f11_attention(struct rmi_function_dev *fn_dev,
        return 0;
 }
 
+#if NV_NOTIFY_OUT_OF_IDLE
+static int rmi_f11_out_of_idle(struct rmi_function_dev *fn_dev)
+{
+       struct f11_data *f11 = fn_dev->data;
+       struct f11_2d_sensor *sensor;
+       int i;
+
+       for (i = 0; i < f11->dev_query.nbr_of_sensors + 1; i++) {
+               sensor = &f11->sensors[i];
+               input_event(sensor->input, EV_MSC, MSC_ACTIVITY, 1);
+       }
+
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_PM
 static int rmi_f11_resume(struct rmi_function_dev *fn_dev)
 {
@@ -2713,10 +2733,13 @@ static struct rmi_function_driver function_driver = {
        .config = rmi_f11_config,
        .attention = rmi_f11_attention,
 #ifdef CONFIG_HAS_EARLYSUSPEND
-       .late_resume = rmi_f11_resume
+       .late_resume = rmi_f11_resume,
 #elif defined(CONFIG_PM)
-       .resume = rmi_f11_resume
+       .resume = rmi_f11_resume,
 #endif  /* defined(CONFIG_HAS_EARLYSUSPEND) */
+#if NV_NOTIFY_OUT_OF_IDLE
+       .out_of_idle = rmi_f11_out_of_idle,
+#endif
 };
 
 static int __init rmi_f11_module_init(void)
index 01764c0..daed901 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
+ * Copyright (C) 2013, NVIDIA Corporation.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
@@ -41,6 +42,10 @@ static char *spi_v2_proto_name = "spiv2";
 
 #define BUFFER_SIZE_INCREMENT 32
 
+#if NV_NOTIFY_OUT_OF_IDLE
+#define RMI_IDLE_PERIOD (msecs_to_jiffies(50))
+#endif
+
 struct rmi_spi_data {
        struct mutex page_mutex;
        int page;
@@ -61,6 +66,9 @@ struct rmi_spi_data {
        struct dentry *debugfs_comms;
        struct dentry *debugfs_ff;
 #endif
+#if NV_NOTIFY_OUT_OF_IDLE
+       unsigned long last_irq_jiffies;
+#endif
 };
 
 #ifdef CONFIG_RMI4_DEBUG
@@ -247,6 +255,25 @@ static void teardown_debugfs(struct rmi_spi_data *data)
 #define teardown_debugfs(data)
 #endif
 
+#if NV_NOTIFY_OUT_OF_IDLE
+static void rmi_spi_out_of_idle(struct rmi_driver_data *rmi_data)
+{
+       struct rmi_function_dev *fn_dev;
+       struct rmi_function_driver *fn_drv;
+
+       /* For now we don't care about to which function dev this irq
+        * corresponds, call all registered out_of_idle handlers.
+        */
+       list_for_each_entry(fn_dev, &rmi_data->rmi_functions.list, list) {
+               if (fn_dev && fn_dev->dev.driver) {
+                       fn_drv = to_rmi_function_driver(fn_dev->dev.driver);
+                       if (fn_drv->out_of_idle)
+                               fn_drv->out_of_idle(fn_dev);
+               }
+       }
+}
+#endif
+
 #define COMMS_DEBUG(data) (IS_ENABLED(CONFIG_RMI4_DEBUG) && data->comms_debug)
 #define FF_DEBUG(data) (IS_ENABLED(CONFIG_RMI4_DEBUG) && data->ff_debug)
 #define IRQ_DEBUG(data) (IS_ENABLED(CONFIG_RMI4_DEBUG) && data->irq_debug)
@@ -272,6 +299,12 @@ static irqreturn_t rmi_spi_hard_irq(int irq, void *p)
                return IRQ_HANDLED;
        }
 
+#if NV_NOTIFY_OUT_OF_IDLE
+       if (time_after(jiffies, data->last_irq_jiffies + RMI_IDLE_PERIOD))
+               rmi_spi_out_of_idle(rmi_data);
+       data->last_irq_jiffies = jiffies;
+#endif
+
        return IRQ_WAKE_THREAD;
 }
 
@@ -806,6 +839,10 @@ static int rmi_spi_probe(struct spi_device *spi)
        data->enabled = true;   /* We plan to come up enabled. */
        data->phys = rmi_phys;
 
+#if NV_NOTIFY_OUT_OF_IDLE
+       data->last_irq_jiffies = jiffies;
+#endif
+
        rmi_phys->data = data;
        rmi_phys->dev = &spi->dev;
 
index 778eb30..5bf0124 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2011, 2012 Synaptics Incorporated
  * Copyright (c) 2011 Unixphere
+ * Copyright (C) 2013, NVIDIA Corporation.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
@@ -29,6 +30,13 @@ extern struct bus_type rmi_bus_type;
 extern struct device_type rmi_function_type;
 extern struct device_type rmi_sensor_type;
 
+/* When NV_NOTIFY_OUT_OF_IDLE is set no rmi spi interrupt for 50ms will be
+ * considered as idle. On first interrupt after idle miscellaneous input
+ * event MSC_ACTIVITY will be sent. This event will serve as early
+ * notification for actual input event and will allow cpu frequency governor
+ * to boost CPU clk early.
+ */
+#define NV_NOTIFY_OUT_OF_IDLE  1
 
 /* Permissions for sysfs attributes.  Since the permissions policy will change
  * on a global basis in the future, rather than edit all sysfs attrs everywhere
@@ -409,6 +417,9 @@ struct rmi_function_driver {
        int (*late_resume)(struct rmi_function_dev *fc);
 #endif
 #endif
+#ifdef NV_NOTIFY_OUT_OF_IDLE
+       int (*out_of_idle)(struct rmi_function_dev *fc);
+#endif
 };
 
 #define to_rmi_function_driver(d) \