video: tegra: host: Add ISP & VI power gating
Terje Bergstrom [Tue, 18 Jun 2013 11:55:37 +0000 (14:55 +0300)]
ISP and VI are both in VE domain, so they have to have a common
power domain. nvhost_module_add_domain() will not first try to add
to an existing domain with the same name, and if that doesn't work,
creates a new one.

Use this mechanism to put VI and ISP devices in the common VE domain.

Conflicts:
drivers/video/tegra/host/isp/isp.c
drivers/video/tegra/host/nvhost_acm.c

Change-Id: Ib630a81ed514c88d9342579655ed80540c7b3c9d
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/241905
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/video/tegra/host/isp/isp.c
drivers/video/tegra/host/nvhost_acm.c
drivers/video/tegra/host/vi/vi.c

index 0f1c091..547d9fd 100644 (file)
@@ -60,6 +60,24 @@ static struct of_device_id tegra_isp_of_match[] = {
        { },
 };
 
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+static int isp_unpowergate(struct generic_pm_domain *domain)
+{
+       struct nvhost_device_data *pdata;
+
+       pdata = container_of(domain, struct nvhost_device_data, pd);
+       return nvhost_module_power_on(pdata->pdev);
+}
+
+static int isp_powergate(struct generic_pm_domain *domain)
+{
+       struct nvhost_device_data *pdata;
+
+       pdata = container_of(domain, struct nvhost_device_data, pd);
+       return nvhost_module_power_off(pdata->pdev);
+}
+#endif
+
 static int isp_probe(struct platform_device *dev)
 {
        int err = 0;
@@ -85,6 +103,22 @@ static int isp_probe(struct platform_device *dev)
        platform_set_drvdata(dev, pdata);
        nvhost_module_init(dev);
 
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+       pdata->pd.name = "ve";
+       pdata->pd.power_off = isp_powergate;
+       pdata->pd.power_on = isp_unpowergate;
+       pdata->pd.dev_ops.start = nvhost_module_enable_clk;
+       pdata->pd.dev_ops.stop = nvhost_module_disable_clk;
+
+       /* add module power domain and also add its domain
+        * as sub-domain of MC domain */
+       err = nvhost_module_add_domain(&pdata->pd, dev);
+
+       /* overwrite save/restore fptrs set by pm_genpd_init */
+       pdata->pd.domain.ops.suspend = nvhost_client_device_suspend;
+       pdata->pd.domain.ops.resume = nvhost_client_device_resume;
+#endif
+
        err = nvhost_client_device_get_resources(dev);
        if (err)
                return err;
@@ -93,12 +127,12 @@ static int isp_probe(struct platform_device *dev)
        if (err)
                return err;
 
-       tegra_pd_add_device(&dev->dev);
        if (pdata->clockgate_delay) {
                pm_runtime_set_autosuspend_delay(&dev->dev,
                        pdata->clockgate_delay);
                pm_runtime_use_autosuspend(&dev->dev);
        }
+
        pm_runtime_enable(&dev->dev);
 
        return 0;
index 15039e6..1252acc 100644 (file)
@@ -589,11 +589,14 @@ int nvhost_module_add_domain(struct generic_pm_domain *domain,
                pm_domain_gov = &pm_domain_always_on_gov;
 #endif
 
-       pm_genpd_init(domain, pm_domain_gov, true);
-       ret = pm_genpd_add_device(domain, &pdev->dev);
-       if (pdata->powergate_delay)
-               pm_genpd_set_poweroff_delay(domain, pdata->powergate_delay);
-       tegra_pd_add_sd(domain);
+       if (__pm_genpd_name_add_device(domain->name, &pdev->dev, NULL)) {
+               pm_genpd_init(domain, pm_domain_gov, true);
+               ret = pm_genpd_add_device(domain, &pdev->dev);
+               if (pdata->powergate_delay)
+                       pm_genpd_set_poweroff_delay(domain,
+                                       pdata->powergate_delay);
+               tegra_pd_add_sd(domain);
+       }
 
        return ret;
 }
index 2159507..619440b 100644 (file)
@@ -61,6 +61,24 @@ static struct of_device_id tegra_vi_of_match[] = {
        { },
 };
 
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+static int vi_unpowergate(struct generic_pm_domain *domain)
+{
+       struct nvhost_device_data *pdata;
+
+       pdata = container_of(domain, struct nvhost_device_data, pd);
+       return nvhost_module_power_on(pdata->pdev);
+}
+
+static int vi_powergate(struct generic_pm_domain *domain)
+{
+       struct nvhost_device_data *pdata;
+
+       pdata = container_of(domain, struct nvhost_device_data, pd);
+       return nvhost_module_power_off(pdata->pdev);
+}
+#endif
+
 static int vi_probe(struct platform_device *dev)
 {
        int err = 0;
@@ -104,6 +122,23 @@ static int vi_probe(struct platform_device *dev)
        mutex_init(&pdata->lock);
        platform_set_drvdata(dev, pdata);
        nvhost_module_init(dev);
+
+#ifdef CONFIG_PM_GENERIC_DOMAINS
+       pdata->pd.name = "ve";
+       pdata->pd.power_off = vi_powergate;
+       pdata->pd.power_on = vi_unpowergate;
+       pdata->pd.dev_ops.start = nvhost_module_enable_clk;
+       pdata->pd.dev_ops.stop = nvhost_module_disable_clk;
+
+       /* add module power domain and also add its domain
+        * as sub-domain of MC domain */
+       err = nvhost_module_add_domain(&pdata->pd, dev);
+
+       /* overwrite save/restore fptrs set by pm_genpd_init */
+       pdata->pd.domain.ops.suspend = nvhost_client_device_suspend;
+       pdata->pd.domain.ops.resume = nvhost_client_device_resume;
+#endif
+
        err = nvhost_client_device_get_resources(dev);
        if (err)
                goto camera_register_fail;