video: tegra: host: gk20a: Add EMC scaling
Arto Merilainen [Tue, 24 Sep 2013 07:13:48 +0000 (10:13 +0300)]
This patch enables EMC scaling on gk20a. We use the same quadratic
relationship that we have used on earlier SoCs.

Bug 1374521

Change-Id: I16cc7b7ec114394d67143387f2bb6fc94ab523b9
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/278232
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Ilan Aelion <iaelion@nvidia.com>
Tested-by: Ilan Aelion <iaelion@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
(cherry picked from commit 3acb168651fa1c4f5022a9af35703b9da5261f4c)
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>

drivers/video/tegra/host/gk20a/gk20a_scale.c
drivers/video/tegra/host/gk20a/gk20a_scale.h
drivers/video/tegra/host/gr3d/scale3d.h
drivers/video/tegra/host/t124/t124.c

index 3b51efa..69cd488 100644 (file)
@@ -35,6 +35,7 @@
 #include "clk_gk20a.h"
 #include "nvhost_scale.h"
 #include "gk20a_scale.h"
+#include "gr3d/scale3d.h"
 
 static ssize_t nvhost_gk20a_scale_load_show(struct device *dev,
                                            struct device_attribute *attr,
@@ -57,6 +58,25 @@ static ssize_t nvhost_gk20a_scale_load_show(struct device *dev,
 static DEVICE_ATTR(load, S_IRUGO, nvhost_gk20a_scale_load_show, NULL);
 
 /*
+ * nvhost_gk20a_scale_callback(profile, freq)
+ *
+ * This function sets emc frequency based on current gpu frequency
+ */
+
+void nvhost_gk20a_scale_callback(struct nvhost_device_profile *profile,
+                                unsigned long freq)
+{
+       struct gk20a *g = get_gk20a(profile->pdev);
+       struct nvhost_device_data *pdata =
+               platform_get_drvdata(profile->pdev);
+       struct nvhost_emc_params *emc_params = profile->private_data;
+       long after = gk20a_clk_get_rate(g);
+       long emc_target = nvhost_scale3d_get_emc_rate(emc_params, after);
+
+       clk_set_rate(pdata->clk[2], emc_target);
+}
+
+/*
  * nvhost_scale_make_freq_table(profile)
  *
  * This function initialises the frequency table for the given device profile
@@ -209,15 +229,22 @@ void nvhost_gk20a_scale_init(struct platform_device *pdev)
        struct gk20a *g = get_gk20a(pdev);
        struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
        struct nvhost_device_profile *profile;
+       struct nvhost_emc_params *emc_params;
 
        if (pdata->power_profile)
                return;
 
        profile = kzalloc(sizeof(struct nvhost_device_profile), GFP_KERNEL);
-       if (!profile)
+       emc_params = kzalloc(sizeof(*emc_params), GFP_KERNEL);
+       if (!(profile && emc_params)) {
+               kfree(profile);
+               kfree(emc_params);
                return;
+       }
+
        profile->pdev = pdev;
        profile->last_event_type = DEVICE_IDLE;
+       profile->private_data = emc_params;
 
        /* Initialize devfreq related structures */
        profile->dev_stat.private_data = &profile->ext_stat;
@@ -231,6 +258,9 @@ void nvhost_gk20a_scale_init(struct platform_device *pdev)
                goto err_fetch_clocks;
        }
 
+       nvhost_scale3d_calibrate_emc(emc_params,
+                                    gk20a_clk_get(g), pdata->clk[2]);
+
        if (device_create_file(&pdev->dev, &dev_attr_load))
                goto err_create_sysfs_entry;
 
index 661e34f..65732b7 100644 (file)
@@ -16,8 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NVHOST_SCALE_H
-#define NVHOST_SCALE_H
+#ifndef GK20A_SCALE_H
+#define GK20A_SCALE_H
 
 #include <linux/nvhost.h>
 #include <linux/devfreq.h>
@@ -41,4 +41,6 @@ void nvhost_gk20a_scale_notify_idle(struct platform_device *);
 
 void nvhost_gk20a_scale_hw_init(struct platform_device *);
 
+void nvhost_gk20a_scale_callback(struct nvhost_device_profile *profile,
+                                unsigned long freq);
 #endif
index 00b6491..076349a 100644 (file)
@@ -45,4 +45,6 @@ void nvhost_scale3d_callback(struct nvhost_device_profile *profile,
 
 void nvhost_scale3d_calibrate_emc(struct nvhost_emc_params *emc_params,
                                  struct clk *clk_3d, struct clk *clk_3d_emc);
+long nvhost_scale3d_get_emc_rate(struct nvhost_emc_params *emc_params,
+                                long freq);
 #endif
index c0853f0..af0e78c 100644 (file)
@@ -33,6 +33,7 @@
 #include "syncpt_t124.h"
 
 #include "gk20a/gk20a.h"
+#include "gk20a/gk20a_scale.h"
 #include "t20/t20.h"
 #include "vic03/vic03.h"
 #include "msenc/msenc.h"
@@ -454,6 +455,7 @@ struct nvhost_device_data tegra_gk20a_info = {
        .scaling_deinit         = nvhost_gk20a_scale_deinit,
        .suspend_ndev           = nvhost_scale3d_suspend,
        .devfreq_governor       = &nvhost_podgov,
+       .scaling_post_cb        = nvhost_gk20a_scale_callback,
 #endif
 };