ARM: tegra12: dvfs: Add alternative display DVFS table
Alex Frid [Tue, 19 Nov 2013 06:53:29 +0000 (22:53 -0800)]
Added display DVFS table applicable only when one window B is active.
Updated comments on multiple display and sdmmc tables.

Bug 1397158

Change-Id: Ie18c9f607f31ee7c185a07df43d424f32b7b79df
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/333093
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

arch/arm/mach-tegra/tegra12_dvfs.c

index 64bd06f..3b324c9 100644 (file)
@@ -313,10 +313,24 @@ static struct dvfs core_dvfs_table[] = {
 };
 
 /*
- * Separate sdmmc and display dvfs table to handle dependency of sdmmc
- * tuning on display maximum rate.
+ * Separate sdmmc and display dvfs table to handle dependency of sdmmc tuning
+ * on display maximum rate.
  *
- * FIXME: details
+ * Display peak voltage aggregation into override range floor is deferred until
+ * actual pixel clock for the particular platform is known. This would allow to
+ * extend sdmmc tuning range on the platforms that do not excercise maximum
+ * display clock capabilities specified in DVFS table.
+ *
+ * Two SDMMC tables:
+ *  - "1-point tuning" table is applicable when override floor is equal to
+ *  nominal voltage (override range is zero). It is installed by default, while
+ *  display peak voltage is unknown. It is overwritten when display peak voltage
+ *  is aggregated, provided final override floor is below nominal.
+ *
+ *  - "2-point tuning" table is applicable when override floor is below nominal
+ *  voltage (i.e., at least 2 tuning points in override range). It is installed
+ *  when display peak voltage is aggregated, provided final override floor is
+ *  below nominal.
  */
 #define OVRRD_DVFS(_clk_name, _speedo_id, _process_id, _auto, _mult, _freqs...) \
        {                                                       \
@@ -374,6 +388,18 @@ static struct dvfs disp_dvfs_table[] = {
        DEFER_DVFS("disp2",       1, -1, 0, KHZ,  192000, 247000, 306000, 342000, 400000, 432000, 474000, 535000),
 };
 
+/* Alternative display dvfs table: applicable if only one window B is active */
+static struct dvfs disp_alt_dvfs_table[] = {
+       /* Core voltages (mV):                    800,    850,    900,    950,    1000,   1050,   1100,   1150 */
+       DEFER_DVFS("disp1",       0,  0, 0, KHZ,  216000, 272000, 330000, 400000, 456000, 490000, 490000, 490000),
+       DEFER_DVFS("disp1",       0,  1, 0, KHZ,  216000, 280000, 342000, 408000, 480000, 490000, 490000, 490000),
+       DEFER_DVFS("disp1",       1, -1, 0, KHZ,  216000, 280000, 342000, 408000, 480000, 506000, 535000, 535000),
+
+       DEFER_DVFS("disp2",       0,  0, 0, KHZ,  216000, 272000, 330000, 400000, 456000, 490000, 490000, 490000),
+       DEFER_DVFS("disp2",       0,  1, 0, KHZ,  216000, 280000, 342000, 408000, 480000, 490000, 490000, 490000),
+       DEFER_DVFS("disp2",       1, -1, 0, KHZ,  216000, 280000, 342000, 408000, 480000, 506000, 535000, 535000),
+};
+
 static int resolve_core_override(int min_override_mv)
 {
        int i, j;
@@ -603,6 +629,28 @@ static bool __init match_dvfs_one(const char *name,
        return true;
 }
 
+static void __init init_alt_dvfs_one(struct dvfs *alt_d)
+{
+       int ret, i;
+       struct clk *c = tegra_get_clock_by_name(alt_d->clk_name);
+
+       if (!c || !c->dvfs) {
+               pr_debug("tegra12_dvfs: invalid alt dvfs for %s\n",
+                       alt_d->clk_name);
+               return;
+       }
+
+       if ((c->dvfs->speedo_id == alt_d->speedo_id) &&
+           (c->dvfs->process_id == alt_d->process_id)) {
+               for (i = 0; i < c->dvfs->num_freqs; i++)
+                       alt_d->freqs[i] *= alt_d->freqs_mult;
+               ret = tegra_dvfs_alt_freqs_install(c->dvfs, alt_d->freqs);
+               if (ret)
+                       pr_err("tegra12_dvfs: failed install alt dvfs on %s\n",
+                              c->name);
+       }
+}
+
 /* cvb_mv = ((c2 * speedo / s_scale + c1) * speedo / s_scale + c0) / v_scale */
 static inline int get_cvb_voltage(int speedo, int s_scale,
                                  struct cvb_dvfs_parameters *cvb)
@@ -1040,6 +1088,9 @@ void __init tegra12x_init_dvfs(void)
                                     ARRAY_SIZE(sdmmc_dvfs_table));
                INIT_CORE_DVFS_TABLE(disp_dvfs_table,
                                     ARRAY_SIZE(disp_dvfs_table));
+
+               for (i = 0; i <  ARRAY_SIZE(disp_alt_dvfs_table); i++)
+                       init_alt_dvfs_one(&disp_alt_dvfs_table[i]);
        }
 
        /* Initialize matching gpu dvfs entry already found when nominal