i2c: tegra: Add early_suspend support for always on i2c-clocks
Chaitanya Bandi [Mon, 3 Sep 2012 08:56:02 +0000 (13:56 +0530)]
Added early_suspend support for always_on i2c clocks such that
they are disabled after blank screen.

Bug 1040399
Bug 1054627

Change-Id: I61fad80f77c8299e850b7cb672f6b7a02ef1d89a
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/130633
(cherry picked from commit 05238e6e8cc67a0b582f9ef5d3751a1789fe5833)
Reviewed-on: http://git-master/r/191533
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>

drivers/i2c/busses/i2c-tegra.c

index 003ceb1..8210c02 100644 (file)
@@ -41,6 +41,9 @@
 
 #include <mach/clk.h>
 #include <mach/pinmux.h>
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
 
 #define TEGRA_I2C_TIMEOUT                      (msecs_to_jiffies(1000))
 #define TEGRA_I2C_RETRIES                      3
@@ -228,8 +231,18 @@ struct tegra_i2c_dev {
        int (*arb_recovery)(int scl_gpio, int sda_gpio);
        struct tegra_i2c_chipdata *chipdata;
        struct tegra_i2c_bus busses[1];
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+       struct early_suspend early_suspend;
+#endif
+
 };
 
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#define EARLY_SUSPEND_LEVEL_MAX                EARLY_SUSPEND_LEVEL_DISABLE_FB
+static void tegra_i2c_early_suspend(struct early_suspend *es);
+static void tegra_i2c_early_resume(struct early_suspend *es);
+#endif
+
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
 {
        writel(val, i2c_dev->base + reg);
@@ -1216,6 +1229,16 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->slave_addr = plat->slave_addr;
        i2c_dev->hs_master_code = plat->hs_master_code;
        i2c_dev->is_dvc = plat->is_dvc;
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+       if (i2c_dev->is_clkon_always) {
+               i2c_dev->early_suspend.level = EARLY_SUSPEND_LEVEL_MAX + 1;
+               i2c_dev->early_suspend.suspend = tegra_i2c_early_suspend;
+               i2c_dev->early_suspend.resume = tegra_i2c_early_resume;
+               register_early_suspend(&i2c_dev->early_suspend);
+       }
+#endif
+
        init_completion(&i2c_dev->msg_complete);
 
        if (!i2c_dev->chipdata->has_xfer_complete_interrupt)
@@ -1311,6 +1334,43 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static void tegra_i2c_early_suspend(struct early_suspend *es)
+{
+       struct tegra_i2c_dev *i2c_dev;
+       i2c_dev = container_of(es, struct tegra_i2c_dev, early_suspend);
+
+       rt_mutex_lock(&i2c_dev->dev_lock);
+
+       i2c_dev->is_suspended = true;
+       tegra_i2c_clock_disable(i2c_dev);
+
+       rt_mutex_unlock(&i2c_dev->dev_lock);
+}
+
+static void tegra_i2c_early_resume(struct early_suspend *es)
+{
+       struct tegra_i2c_dev *i2c_dev;
+       int ret;
+
+       i2c_dev = container_of(es, struct tegra_i2c_dev, early_suspend);
+
+       rt_mutex_lock(&i2c_dev->dev_lock);
+
+       tegra_i2c_clock_enable(i2c_dev);
+
+       ret = tegra_i2c_init(i2c_dev);
+       if (ret) {
+               rt_mutex_unlock(&i2c_dev->dev_lock);
+               return;
+       }
+
+       i2c_dev->is_suspended = false;
+
+       rt_mutex_unlock(&i2c_dev->dev_lock);
+}
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 static int tegra_i2c_suspend_noirq(struct device *dev)
 {
@@ -1319,9 +1379,14 @@ static int tegra_i2c_suspend_noirq(struct device *dev)
 
        rt_mutex_lock(&i2c_dev->dev_lock);
 
-       i2c_dev->is_suspended = true;
+#ifndef CONFIG_HAS_EARLYSUSPEND
        if (i2c_dev->is_clkon_always)
                tegra_i2c_clock_disable(i2c_dev);
+       i2c_dev->is_suspended = true;
+#else
+       if (!i2c_dev->is_clkon_always)
+               i2c_dev->is_suspended = true;
+#endif
 
        rt_mutex_unlock(&i2c_dev->dev_lock);
 
@@ -1336,17 +1401,31 @@ static int tegra_i2c_resume_noirq(struct device *dev)
 
        rt_mutex_lock(&i2c_dev->dev_lock);
 
+       (void) ret;
+
+#ifndef CONFIG_HAS_EARLYSUSPEND
        if (i2c_dev->is_clkon_always)
                tegra_i2c_clock_enable(i2c_dev);
 
        ret = tegra_i2c_init(i2c_dev);
-
        if (ret) {
                rt_mutex_unlock(&i2c_dev->dev_lock);
                return ret;
        }
 
        i2c_dev->is_suspended = false;
+#else
+       if (!i2c_dev->is_clkon_always) {
+               ret = tegra_i2c_init(i2c_dev);
+               if (ret) {
+                       rt_mutex_unlock(&i2c_dev->dev_lock);
+                       return ret;
+               }
+               i2c_dev->is_suspended = false;
+       }
+#endif
+
+
 
        rt_mutex_unlock(&i2c_dev->dev_lock);