Use the PM-WIP-OPP branch apis for generating the opp list for DSP.
This allows for scaling accross 3430,3440,3450 and 3630 series.

Caveat: does not handle dynamic addition of opp after the
bridgedriver is inserted - this can be done once the framework for
the same is made available

Cc: Ameya Palande <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Deepak Chitriki <[email protected]>
Cc: Fernando Guzman Lugo <[email protected]>
Cc: Felipe Contreras <[email protected]>
Cc: Hari Kanigeri <[email protected]>
Cc: Hiroshi Doyu <[email protected]>
Cc: Omar Ramirez Luna <[email protected]>
Cc: Ramesh Gupta <[email protected]>

Signed-off-by: Nishanth Menon <[email protected]>
---
Ref:
v1: http://marc.info/?t=126402609100005&r=1&w=2
changes for v2:
 rebase on patch 2/2

 arch/arm/mach-omap2/dspbridge.c |  138 ++++++++++++++++++++++++---------------
 1 files changed, 85 insertions(+), 53 deletions(-)

diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
index 8527a48..b2d08dc 100644
--- a/arch/arm/mach-omap2/dspbridge.c
+++ b/arch/arm/mach-omap2/dspbridge.c
@@ -15,6 +15,20 @@
 
 #ifdef CONFIG_BRIDGE_DVFS
 #include <plat/omap-pm.h>
+#include <plat/opp.h>
+/*
+ * The DSP load balancer works on the following logic:
+ * Opp frequencies:
+ * 0 <---------> Freq 1 <------------> Freq 2 <---------> Freq 3
+ * DSP Thresholds for the frequencies:
+ * 0M<-------X-> Freq 1 <-------M--X-> Freq 2 <----M--X-> Freq 3
+ * Where, M is the minimal threshold and X is maximum threshold
+ *
+ * if from Freq x to Freq y; where x > y, transition happens on M
+ * if from Freq x to Freq y; where x < y, transition happens on X
+ */
+#define BRIDGE_THRESH_HIGH_PERCENT     95
+#define BRIDGE_THRESH_LOW_PERCENT      88
 #endif
 
 #include <dspbridge/host_os.h>
@@ -42,72 +56,90 @@ static struct dspbridge_platform_data dspbridge_pdata 
__initdata = {
 static int __init get_opp_table(struct dspbridge_platform_data *pdata)
 {
 #ifdef CONFIG_BRIDGE_DVFS
-       /*
-        * TODO: The following code is a direct replacement
-        * improvements are possible.
-        * XXX: Does not support 3630
-        */
+       int mpu_freqs;
+       int dsp_freqs;
        int i;
-       /* legacy values for 3430 */
-       u32 vdd1_dsp_freq[6][4] = {
-               {0, 0, 0, 0},
-               /*OPP1*/
-               {0, 90000, 0, 86000},
-               /*OPP2*/
-               {0, 180000, 80000, 170000},
-               /*OPP3*/
-               {0, 360000, 160000, 340000},
-               /*OPP4*/
-               {0, 396000, 325000, 376000},
-               /*OPP5*/
-               {0, 430000, 355000, 430000},
-       };
-       struct omap_opp vdd1_rate_table_bridge[] = {
-               {0, 0, 0},
-               /*OPP1*/
-               {125000000, VDD1_OPP1, 0},
-               /*OPP2*/
-               {250000000, VDD1_OPP2, 0},
-               /*OPP3*/
-               {500000000, VDD1_OPP3, 0},
-               /*OPP4*/
-               {550000000, VDD1_OPP4, 0},
-               /*OPP5*/
-               {600000000, VDD1_OPP5, 0},
-       };
-       pdata->mpu_num_speeds = VDD1_OPP5;
-       pdata->mpu_speeds = kzalloc(sizeof(u32) * (pdata->mpu_num_speeds + 1),
+       struct omap_opp *opp;
+       unsigned long freq, old_rate;
+
+       mpu_freqs = opp_get_opp_count(OPP_MPU);
+       dsp_freqs = opp_get_opp_count(OPP_DSP);
+       if (mpu_freqs < 0 || dsp_freqs < 0 || mpu_freqs != dsp_freqs) {
+               pr_err("%s:mpu and dsp frequencies are inconsistent! "
+                       "mpu_freqs=%d dsp_freqs=%d\n", __func__, mpu_freqs,
+                       dsp_freqs);
+               return -EINVAL;
+       }
+       /* allocate memory if we have opps initialized */
+       pdata->mpu_speeds = kzalloc(sizeof(u32) * mpu_freqs,
                        GFP_KERNEL);
        if (!pdata->mpu_speeds) {
-               pr_err("%s: unable to allocate memory for the mpu"
-               "frequencies\n", __func__);
+               pr_err("%s:unable to allocate memory for the mpu"
+                       "frequencies\n", __func__);
                return -ENOMEM;
        }
-       pdata->dsp_num_speeds = VDD1_OPP5;
+       i = 0;
+       freq = 0;
+       while (!IS_ERR(opp = opp_find_freq_ceil(OPP_MPU, &freq))) {
+               pdata->mpu_speeds[i] = freq;
+               freq++;
+               i++;
+       }
+       pdata->mpu_num_speeds = mpu_freqs;
+       pdata->mpu_min_speed = pdata->mpu_speeds[0];
+       pdata->mpu_max_speed = pdata->mpu_speeds[mpu_freqs - 1];
+       /* need an initial terminator */
        pdata->dsp_freq_table = kzalloc(
                        sizeof(struct dsp_shm_freq_table) *
-                       (pdata->dsp_num_speeds + 1), GFP_KERNEL);
+                       (dsp_freqs + 1), GFP_KERNEL);
        if (!pdata->dsp_freq_table) {
                pr_err("%s: unable to allocate memory for the dsp"
-               "frequencies\n", __func__);
-               kfree(pdata->mpu_speeds);
-               pdata->mpu_speeds = NULL;
+                       "frequencies\n", __func__);
                return -ENOMEM;
        }
-       for (i = 0; i <= pdata->mpu_num_speeds; i++)
-               pdata->mpu_speeds[i] = vdd1_rate_table_bridge[i].rate;
-       pdata->mpu_max_speed = pdata->mpu_speeds[VDD1_OPP5];
-       pdata->mpu_min_speed = pdata->mpu_speeds[VDD1_OPP1];
-
-       for (i = 0; i <= pdata->dsp_num_speeds; i++) {
-               pdata->dsp_freq_table[i].u_volts =
-                               vdd1_dsp_freq[i][0];
-               pdata->dsp_freq_table[i].dsp_freq = vdd1_dsp_freq[i][1];
-               pdata->dsp_freq_table[i].thresh_min_freq =
-                       vdd1_dsp_freq[i][2];
-               pdata->dsp_freq_table[i].thresh_max_freq =
-                       vdd1_dsp_freq[i][3];
+
+       i = 1;
+       freq = 0;
+       old_rate = 0;
+       /*
+        * the freq table is in terms of khz.. so we need to
+        * divide by 1000
+        */
+       while (!IS_ERR(opp = opp_find_freq_ceil(OPP_DSP, &freq))) {
+               /* dsp frequencies are in khz */
+               u32 rate = freq / 1000;
+
+               /*
+                * On certain 34xx silicons, certain OPPs are duplicated
+                * for DSP - handle those by copying previous opp value
+                */
+               if (rate == old_rate) {
+                       memcpy(&pdata->dsp_freq_table[i],
+                               &pdata->dsp_freq_table[i-1],
+                               sizeof(struct dsp_shm_freq_table));
+               } else {
+                       pdata->dsp_freq_table[i].dsp_freq = rate;
+                       pdata->dsp_freq_table[i].u_volts =
+                               opp_get_voltage(opp);
+                       /*
+                        * min threshold:
+                        * NOTE: index 1 needs a min of 0! else no
+                        * scaling happens at DSP!
+                        */
+                       pdata->dsp_freq_table[i].thresh_min_freq =
+                               ((old_rate * BRIDGE_THRESH_LOW_PERCENT) / 100);
+
+                       /* max threshold */
+                       pdata->dsp_freq_table[i].thresh_max_freq =
+                               ((rate * BRIDGE_THRESH_HIGH_PERCENT) / 100);
+               }
+               old_rate = rate;
+               freq++;
+               i++;
        }
+       /* the last entry should map with maximum rate */
+       pdata->dsp_freq_table[i - 1].thresh_max_freq = old_rate;
+       pdata->dsp_num_speeds = dsp_freqs;
 #endif
        return 0;
 }
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to