video: tegra: host: Support linear EMC scaling
Arto Merilainen [Wed, 25 Sep 2013 11:05:47 +0000 (14:05 +0300)]
Some units have strict linear relationship between unit clock and
required memory bandwidth, however, currently automatic EMC
relationship computation expects a non-linear relationship. This
patch adds a flag to nvhost device data to indicate if the
EMC should be scaled based using linear relationship.

Bug 1364804

Change-Id: I68fbb06de33fdeeb1c0e3c6b1db1f69c99e0e14e
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
(cherry picked from commit 9897a5854b24a48d0acace8e4371cdefa44253a4)
Signed-off-by: Ajay Nandakumar <anandakumarm@nvidia.com>

drivers/video/tegra/host/gk20a/gk20a_scale.c
drivers/video/tegra/host/gr3d/scale3d.c
drivers/video/tegra/host/gr3d/scale3d.h
include/linux/nvhost.h

index 69cd488..e2e740c 100644 (file)
@@ -259,7 +259,8 @@ void nvhost_gk20a_scale_init(struct platform_device *pdev)
        }
 
        nvhost_scale3d_calibrate_emc(emc_params,
-                                    gk20a_clk_get(g), pdata->clk[2]);
+                                    gk20a_clk_get(g), pdata->clk[2],
+                                    pdata->linear_emc);
 
        if (device_create_file(&pdev->dev, &dev_attr_load))
                goto err_create_sysfs_entry;
index 70f4801..18b0f86 100644 (file)
@@ -84,10 +84,13 @@ long nvhost_scale3d_get_emc_rate(struct nvhost_emc_params *emc_params,
 
        freq = INT_TO_FX(HZ_TO_MHZ(freq));
        hz = FXMUL(freq, emc_params->emc_slope) + emc_params->emc_offset;
-       hz -= FXMUL(emc_params->emc_dip_slope,
-               FXMUL(freq - emc_params->emc_xmid,
-                       freq - emc_params->emc_xmid)) +
-               emc_params->emc_dip_offset;
+
+       if (!emc_params->linear)
+               hz -= FXMUL(emc_params->emc_dip_slope,
+                       FXMUL(freq - emc_params->emc_xmid,
+                               freq - emc_params->emc_xmid)) +
+                       emc_params->emc_dip_offset;
+
        hz = MHZ_TO_HZ(FX_TO_INT(hz + FX_HALF)); /* round to nearest */
        hz = (hz < 0) ? 0 : hz;
 
@@ -172,7 +175,8 @@ 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)
+                                 struct clk *clk_3d, struct clk *clk_3d_emc,
+                                 bool linear_emc)
 {
        long correction;
        unsigned long max_emc;
@@ -201,6 +205,10 @@ void nvhost_scale3d_calibrate_emc(struct nvhost_emc_params *emc_params,
                (FXMUL(emc_params->emc_slope, max_rate_3d) +
                emc_params->emc_offset);
 
+       emc_params->linear = linear_emc;
+       if (linear_emc)
+               return;
+
        emc_params->emc_dip_offset = (max_emc - min_emc) / 4;
        emc_params->emc_dip_slope =
                -4 * FXDIV(emc_params->emc_dip_offset,
@@ -248,7 +256,8 @@ void nvhost_scale3d_init(struct platform_device *pdev)
 
        nvhost_scale3d_calibrate_emc(&gr3d_params->emc_params,
                                     clk(profile, gr3d_params->clk_3d),
-                                    clk(profile, gr3d_params->clk_3d_emc));
+                                    clk(profile, gr3d_params->clk_3d_emc),
+                                    pdata->linear_emc);
 
        return;
 
index 076349a..81f4071 100644 (file)
@@ -32,6 +32,7 @@ struct nvhost_emc_params {
        long                            emc_dip_slope;
        long                            emc_dip_offset;
        long                            emc_xmid;
+       bool                            linear;
 };
 
 /* Initialization and de-initialization for module */
@@ -44,7 +45,8 @@ void nvhost_scale3d_callback(struct nvhost_device_profile *profile,
                             unsigned long freq);
 
 void nvhost_scale3d_calibrate_emc(struct nvhost_emc_params *emc_params,
-                                 struct clk *clk_3d, struct clk *clk_3d_emc);
+                                 struct clk *clk_3d, struct clk *clk_3d_emc,
+                                 bool linear_emc);
 long nvhost_scale3d_get_emc_rate(struct nvhost_emc_params *emc_params,
                                 long freq);
 #endif
index 8960277..af09ad9 100644 (file)
@@ -207,6 +207,8 @@ struct nvhost_device_data {
        struct nvhost_device_profile    *power_profile;
        /* Should we read load estimate from hardware? */
        bool                            actmon_enabled;
+       /* Should we do linear emc scaling? */
+       bool                            linear_emc;
        /* Offset to actmon registers */
        u32                             actmon_regs;
        /* Devfreq governor name */