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 <ameya.pala...@nokia.com>
Cc: Deepak Chitriki <deepak.chitr...@ti.com>
Cc: Felipe Contreras <felipe.contre...@nokia.com>
Cc: Hiroshi Doyu <hiroshi.d...@nokia.com>
Cc: Omar Ramirez Luna <omar.rami...@ti.com>

Signed-off-by: Nishanth Menon <n...@ti.com>
---
caveat: this does not use the ENUM implementation yet, this can be once it is
merged to pm-wip-opp branch.

 arch/arm/mach-omap2/dspbridge.c |   99 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 98 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
index 26b860f..935afd7 100644
--- a/arch/arm/mach-omap2/dspbridge.c
+++ b/arch/arm/mach-omap2/dspbridge.c
@@ -15,6 +15,20 @@
 
 #ifdef CONFIG_BRIDGE_DVFS
 #include <mach/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,7 +56,90 @@ static struct dspbridge_platform_data dspbridge_pdata 
__initdata = {
 static int get_opp_table(struct dspbridge_platform_data *pdata)
 {
 #ifdef CONFIG_BRIDGE_DVFS
-       /* Do nothing now  - fill based on PM implementation */
+       int mpu_freqs;
+       int dsp_freqs;
+       int i;
+       struct omap_opp *opp;
+       unsigned long freq, old_rate;
+
+       mpu_freqs = opp_get_opp_count(mpu_opps);
+       dsp_freqs = opp_get_opp_count(dsp_opps);
+       if (mpu_freqs < 0 || dsp_freqs < 0 || mpu_freqs != dsp_freqs) {
+               pr_err("mpu and dsp frequencies are inconsistent! "
+                       "mpu_freqs=%d dsp_freqs=%d\n", 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("unable to allocate memory for the mpu"
+               "frequencies\n");
+               return -ENOMEM;
+       }
+       opp = mpu_opps;
+       i = 0;
+       freq = 0;
+       while (!IS_ERR(opp = opp_find_freq_ceil(opp, &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) *
+                       (dsp_freqs + 1), GFP_KERNEL);
+       if (!pdata->dsp_freq_table) {
+               pr_err("unable to allocate memory for the dsp"
+                       "frequencies\n");
+               return -ENOMEM;
+       }
+
+       opp = dsp_opps;
+       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, &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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to